TSQL Cross Apply не работает должным образом

Есть 3 таблицы:

  • Пользователи
  • Отделы (хотя кажется, что это не обязательно для запроса, но...)
  • Сообщения

Пользователи:

       UID, DeptID, Name, Surname,  Admin
        U1  DeptA   John    Doe     0
        U2  DeptB   Jack    Fisher  0
        U3  DeptA   Jill    Smith   0
        U4  DeptA   Joan    Green   1
        U5  DeptC   Jeff    Jones   1
        U6  DeptA   Amanda  Reed    0
        ......

Отделы:

       DeptID, DeptName
        DeptA   Denver
        DeptB   Boston
        DeptC   Seattle

Сообщения:

        Sender, Receiver, Message, CreatedDate, Seen
            U1      U3      Msg1        20152310    0
            U1      U4      Msg2        20152310    0
            U4      U1      Msg3        20152310    0
            U3      U4      Msg4        20152310    0
            U1      U3      Msg5        20152310    0
            U3      U1      Msg6        20152310    0

(Пользователи могут отправлять сообщения только другим пользователям в том же отделе)

с одним входным параметром, таким образом, UID

Мне нужно создать список со всеми пользователями одного и того же отдела (кроме входного UID) в качестве заголовков, поэтому в примере

U3          U4       U6

с их данными (имя, фамилия) для создания списка вкладок

а затем для каждого из указанных выше UID список с последними 20 сообщениями, в которых U1 участвует как отправитель, так и получатель

Чтобы заполнить боковую панель чата, вы можете увидеть здесь: http://www.keenthemes.com/preview/metronic/theme/admin_4/

нажав на правый верхний значок

Я пытался с этим ... но у меня много дубликатов, которые не знают, как удалить: возможно, перекрестное применение - неправильная команда ... :-(

SELECT  u.UID, 
        u.PWD,
        i.Sender,
        I.MessageText
        .....
FROM (
        SELECT  S.UID,
                S.PWD
            FROM dbo.Users  u
            JOIN dbo.Users  u2  ON  u.DeptID=u2.DeptID
            WHERE u2.UID=@_UID
            ORDER BY u.Admin DESC
        ) AS u
CROSS APPLY 
        (
            SELECT TOP (20) 
                    m.Sender, 
                    m.Message, 
                    m.CreatedDate, 
                    m.Seen
            FROM    dbo.Messages m
            WHERE   m.Sender=@_UID 
            OR      m.Receiver=@_UID
            ORDER BY m.CreatedDate DESC
        ) m;

Можете подсказать, что не так?

Спасибо

Джо


person Joe    schedule 23.10.2015    source источник


Ответы (1)


Честно говоря, я не могу точно понять, что ваш запрос пытался сделать. Но, глядя на страницу, на которую вы ссылаетесь, и описание вашей проблемы, похоже, что вы хотите, чтобы запрос заполнял список пользователей (кроме текущего пользователя), а другой - для получения сообщений, относящихся к этому пользователю.

Рассмотрим что-то вроде:

DECLARE @_UID varchar(2) = 'U3';

-- Query for populating list of users
SELECT [UID], [Name] + ' ' + [Surname] AS [FullName]
FROM [dbo].[Users]
WHERE [UID] <> @_UID
ORDER BY [Admin] DESC, [Surname], [Name];

-- Query for populating messages
SELECT TOP 20 S.[UID] AS [SenderUID], S.[Name] + ' ' + S.[Surname] AS [SenderFullName],
    R.[UID] AS [ReceiverUID], R.[Name] + ' ' + R.[Surname] AS [ReceiverFullName],
    M.[Message], M.[CreatedDate], M.[Seen]
FROM [dbo].[Messages] M
    INNER JOIN [dbo].[Users] S ON S.[UID] = M.[Sender]
    INNER JOIN [dbo].[Users] R ON R.[UID] = M.[Receiver]
WHERE @_UID IN(M.[Sender], M.[Receiver])
ORDER BY M.[CreatedDate] DESC;

Что касается использования APPLY, оно похоже на JOIN. При использовании JOIN вы объединяете известный набор результатов (например, содержимое таблицы) с другим набором результатов, который также известен. При использовании APPLY набор результатов правой стороны не обязательно должен быть известен — например, вы можете использовать функцию для вычисления результата на основе результатов левой стороны.

person izzy    schedule 23.10.2015
comment
Привет! Спасибо за ответ. На самом деле моя цель состояла в том, чтобы собрать все вместе в один запрос, но, возможно, гораздо проще сохранить 2 отдельных запроса... Я еще немного подумаю. - person Joe; 24.10.2015
comment
Причина, по которой я бы использовал два запроса, заключается в том, что если у пользователя есть более одного сообщения, они будут в результатах дважды, но тогда в вашем списке пользователей будут дубликаты. Личный опыт также научил меня тому, что несколько небольших запросов, которые возвращают именно то, что я хочу для определенного представления, обычно быстрее, чем попытка использовать вывод более сложного запроса для нескольких представлений. - person izzy; 25.10.2015
comment
Да, я понимаю... и на самом деле это то, что я обычно делаю... но хотелось бы посмотреть, есть ли элегантное решение с одним запросом. - person Joe; 26.10.2015