选择与Groupby中的条件匹配的第一行

时间:2014-05-26 00:36:01

标签: mysql group-by

根据以下消息表,其中频道是特定聊天会话,user1user2是聊天中的用户:

+---------+-------+-------+------------+
| channel | user1 | user2 |  message   |
+---------+-------+-------+------------+
|       5 |    15 |     8 | Hello      |
|       5 |    15 |     8 | I'm John   |
|       5 |     8 |    15 | Hi John    |
|       6 |     9 |    15 | yo         |
|       6 |    15 |     9 | heyo       |
|       6 |     9 |    15 | you here?  |
|       8 |    15 |    10 | Hi         |
|       8 |    15 |    10 | you there? |
+---------+-------+-------+------------+

我想按channel进行分组并选择第一个响应行(第二个人说的第一行)。如果第二个人从未在通道8中响应,则他们不需要显示在输出中。

所以我的预期输出是这样的:

+---------+-------+-------+---------+
| channel | user1 | user2 | message |
+---------+-------+-------+---------+
|       5 |     8 |    15 | Hi John |
|       6 |    15 |     9 | heyo    |
+---------+-------+-------+---------+

请注意,有一个时间戳列,只是忘了包含它。任何帮助将不胜感激,一直在寻找一个尚未提出任何解决方案。感谢。

2 个答案:

答案 0 :(得分:1)

自己并不完全相信。随意改进。 限制1依赖于每次从上到下读取的表。 而且我怀疑所有不同的选择都可以更优雅地完成。 但至少它为样本数据提供了所需的结果:)

SELECT channelchat.channel,
  (SELECT user2 
   FROM chat firstline
   WHERE firstline.channel = channelchat.channel
   LIMIT 1) seconduser,
  (SELECT user1
   FROM chat firstline
   WHERE firstline.channel = channelchat.channel
   LIMIT 1) firstuser,
  (SELECT message 
   FROM chat secondline
   WHERE secondline.channel = channelchat.channel
   AND secondline.user1 = seconduser
   LIMIT 1) response
FROM chat channelchat
GROUP BY channelchat.channel
HAVING response IS NOT NULL

sqlfiddle

答案 1 :(得分:1)

假设您有一个时间戳列,您可以将第一条消息的user2作为:

select m.*
from messages m
where not exists (select 1
                  from messages m2
                  where m2.channel = m.channel and
                        m2.timestamp < m.timestamp
                 );

所以,如果你想要第一条消息,你可以使用group_concat() / substring_index()`技巧:

select m.channel, m.user1, m.user2,
       substring_index(group_concat(m2.messages order by m2.timestemp separator '|'), '|', 1)
from messages m join
     (select m.*
      from messages m
      where not exists (select 1
                        from messages m2
                        where m2.channel = m.channel and
                              m2.timestamp < m.timestamp
                       )
     ) mfirst
     on m.channel = mfirst.channel and
        m.user1 = mfirst.user2
group by m.channel, m.user1, m.user2;