在1个sql查询中对不同列进行分组

时间:2014-05-04 12:50:41

标签: sql sql-server

我有一张包含消息的表格(简化):

MessageId,
FromUserId,
ToUserId,
Text

并希望将查询输出作为这样的聊天列表:

LastMessageId,
UserId,
Text

所以基本上创建一个对FromUserId和ToUserId进行分组的查询,但前提是其中一个是我自己的userId。

所以我想出了这个:

SELECT  (MessageId)
      ,(Text)
      ,(FromUserId)
      ,(ToUserId)
  FROM [Messages] a
  inner join (select FromUserId as FromId, ToUserId as ToId, Max(MessageId) as MaxId from Messages where MessageId > 0 group by FromUserId, ToUserId) as b on
  a.MessageId = b.MaxId 
  join users u on FromUserId = u.userId
  where ToUserId = 123 or FromUserId = 123

有了这个,我就在那里输出(比如123是我的用户ID):

MessageId, Text, FromUserId, ToUserId
1          bla   123         345
2          bla2  345         123
3          bla3  678         123
4          bla4  123         678

我想有这样的输出:

MessageId, Text, UserId
2          bla2  345   
4          bla4  678 

所以我省略了自己的用户ID,并且只有每次会话的最后一条消息。

这可以在1个查询中完成吗?到目前为止,我只是收到所有消息并通过代码处理此消息。

2 个答案:

答案 0 :(得分:1)

SELECT * FROM messages WHERE MessageId IN
(
   SELECT DISTINCT
   CASE WHEN m2.MessageId IS NULL THEN m1.MessageId
   WHEN m1.MessageId > m2.MessageId THEN m1.MessageId ELSE m2.MessageId END
   FROM messages m1
   LEFT JOIN messages m2 ON
   (m1.FROMUSERID = m2.ToUserId
   AND m2.FROMUSERID = m1.ToUserId
   AND m1.MessageId != m2.MessageId)
)
-- AND (messages.FROMUSERID = 123 or messages.ToUserId = 123)

Sqlfiddle Demo

答案 1 :(得分:0)

这是一种方法,首先将消息表组合起来,以获得一列UserId和其他信息。然后,它使用row_number()函数查找每个用户的最新消息,并使用segnum = 1选择该消息:

SELECT MessageId, Text, UserId
FROM (SELECT MessageId, Text, UserId,
             row_number() over (partition by UserId order by MessageId desc) as seqnum
      FROM ((select FromUserId as UserId, MessageId, Text
             Messages m
            ) union all
            (select ToUserId as UserId, MessageId, Text
             Messages m
            )
           ) m
     ) m
WHERE seqnum = 1;

如果要将此限制为一个用户,可以向每个子查询添加where FromUserId = @X or ToUserId = @X(最好在union all之前执行此操作。)