T-SQL Group具有独特的价值

时间:2014-01-27 15:46:33

标签: sql sql-server join group-by distinct

我有这些表格。

用户

|ID|Field1....|

UserMessages

|ID|UserSenderId|UserReceiverId|Message|CreatedOn|

其中UserSenderIdUserReceiverId是PK User.Id

的FK

我想选择用户之间每次对话的第一条消息(比如左边的Facebook,我看到一个用户列表和最后一条消息的第一个字符)

我尝试了这个查询,但我为同一对用户提供了多个结果

SELECT DISTINCT 
    UserMessages.* 
FROM 
    UserMessages 
JOIN 
    (SELECT 
         MAX(UserMessages.Id) AS IDMAX,
         UserMessages.IdReceiver,
         UserMessages.IdSender 
     FROM 
         UserMessages 
     WHERE 
         UserMessages.IdReceiver = @UserId OR UserMessages.IdSender = @UserId 
     GROUP BY 
         UserMessages.IdReceiver, UserMessages.IdSender) IDMAX ON IDMax.IDMAX = UserMessages.Id 

示例

UserMessages

|ID|UserSenderId|UserReceiverId|Message|
  1|46|47|Hello
  2|47|46|Hello!
  3|46|48|Hey!!
  4|50|46|How are you?
  5|51|49| Hello 

考虑到记录的userid = 46,我想只选择标识为2 3 4的消息,其中id = 2是用户46和47之间的最后一个消息(记录的用户可以是发送者或接收者)

谢谢!

1 个答案:

答案 0 :(得分:2)

您可以使用row_number()执行此操作。诀窍是无论发送者和接收者是谁,都要配对消息。您可以先将较小的ID放入,然后再放入较大的ID:

select um.*
from (SELECT um.*,
             row_number() over (partition by (case when idReceiver < idSender then idReceiver else idSender end),
                                             (case when idReceiver < idSender then idSender else idReceiver end)
                                order by id desc
                               ) as seqnum
     from UserMessages um
     where um.IdReceiver = @UserId OR um.IdSender = @UserId
    ) um
where seqnum = 1;