1

我为用户创建了一个消息系统,允许用户向另一个人发送消息。

为此,我创建了两个表。

  conversation(conversation_id,user_id1,user_id2)
  messages(message_id,conversation_id,sender_id,receiver_id,message,created_time)

如果用户是第一次交谈,将使用 user_id1(发起聊天的人)和 user_id2(向 user_id1 正在发送消息的人)创建一个 conversation_id

消息表将包含与消息相关的所有信息。

现在我想要的是,创建一个消息摘要页面,其中登录用户可以查看他在其他用户之间的所有对话列表,按created_time排序,按conversation_id分组。

以下是表格数据:

conversation_id | user_id1 | user_id2
     1                100       103
     2                101       103
     3                103       102        


message_id| conversation_id| sender_id| receiver_id| message | created_time
   1             1            100       103           MSG A    2012-06-08 08:38:57
   2             1            103       100           MSG B    2012-06-08 08:39:40
   3             2            101       103           MSG C    2012-06-08 08:40:20
   4             3            102       103           MSG D    2012-06-08 08:41:10

这是我正在寻找的输出:假设登录用户的 ID 为:103

conversation_id| conversation_with | last_message | created_time
      3              102              MSG D         2012-06-08 08:41:10
      2              101              MSG C         2012-06-08 08:40:20
      1              100              MSG B         2012-06-08 08:39:40

因此,此输出按 created_time 排序,按 conversation_id 分组并在 conversation_with 中显示用户的 id,用户 ID 103 正在与谁进行对话。

有人可以提供 MySQL 查询吗?我需要得到这个输出。

4

1 回答 1

1

这是一个有趣的。因此,您需要解决三个主要问题。

  1. conversation_with根据所需用户在两列中的显示位置交替列。
  2. greatest-n-per-group找到最新的message
  3. least-n-per-group找到最早的消息created_time

第一个问题是我通过查询两次、交替user_id列、合并结果,然后将合并结果按created_time. 我想我可以用一个查询而不用联合来解决这个问题,但它现在有效。

2和3涉及更多一点。这是查询的 SQL 小提琴:http ://sqlfiddle.com/#!2/bf2b7/1

TL;DNR

select * from (
    select c.conversation_id, c.user_id2 as conversation_with, m1.message as last_message, m3.created_time 
    from conversation as c
      join messages as m1 on c.conversation_id = m1.conversation_id
      left outer join messages as m2 on (c.conversation_id = m2.conversation_id 
                                         and (m1.created_time < m2.created_time OR m1.created_time = m2.created_time AND m1.message_id < m2.message_id))
      join messages as m3 on c.conversation_id = m3.conversation_id
      left outer join messages as m4 on (c.conversation_id = m4.conversation_id
                                         and (m3.created_time > m4.created_time OR m3.created_time = m4.created_time AND m3.message_id > m4.message_id))
    where user_id1 = 103 and m2.message_id is null and m4.message_id is null
  union all
    select c.conversation_id, c.user_id1 as conversation_with, m1.message as last_message, m3.created_time 
    from conversation as c
      join messages as m1 on c.conversation_id = m1.conversation_id
      left outer join messages as m2 on (c.conversation_id = m2.conversation_id 
                                         and (m1.created_time < m2.created_time OR m1.created_time = m2.created_time AND m1.message_id < m2.message_id))
      join messages as m3 on c.conversation_id = m3.conversation_id
      left outer join messages as m4 on (c.conversation_id = m4.conversation_id
                                         and (m3.created_time > m4.created_time OR m3.created_time = m4.created_time AND m3.message_id > m4.message_id))
    where user_id2 = 103 and m2.message_id is null and m4.message_id is null
                                        ) as conversations
order by created_time desc
于 2012-06-09T05:40:01.400 回答