繁体   English   中英

私人聊天系统-获取每次聊天的最新消息

[英]Private chat system - get last message of each chat

我正在建立2位用户之间的聊天系统。 我有一个看起来像这样的聊天表:(以下是架构: SQL Fiddle

        --------------------------------------------------------------------------------
        | message_id | sender_id | receiver_id  | message_text  |       date           |
        --------------------------------------------------------------------------------
        |     1      |     20    |      100     |  Hello mate   |  2018-04-29 12:15:33 | 
        --------------------------------------------------------------------------------
        |     2      |    100    |      20      |   Hi there    |  2018-04-29 13:20:05 | 
        --------------------------------------------------------------------------------
        |     3      |     13    |      44      |   Alright     |  2018-04-29 14:35:15 | 
        --------------------------------------------------------------------------------
        |     4      |     20    |      57      |   Hi user 57  |  2018-04-29 16:44:34 | 
        --------------------------------------------------------------------------------

我想从用户进行的每次聊天中获取最后一条消息的行,因此在上面的示例中,用户20应该获得2行:message_id 2行(因为他正在与用户100进行聊天,尽管他没有发送最后一条消息)和message_id 4行(因为他向用户57发送了消息)基本上就像WhatsApp一样,您始终在顶部拥有任何聊天的第一条消息。

问题是,如果用户是SENDER,则我只能得到最后一条消息,而如果他是接收者,则不能:

 SELECT * FROM chat 
 WHERE message_id IN 
(SELECT MAX(message_id) FROM chat WHERE sender_id=:sender_id 
 GROUP BY receiver_id) ORDER BY date DESC

我想我应该添加另一列“ chat_id”,该列对于在同一聊天中的每个2个用户来说都是相同的(因此,无论用户100和20是发送者还是接收者,用户100和20都将具有相同的chat_id,用户13和在此示例中,44将有所不同),

还是有更好的选择?

您可以在发送者和接收者之间使用联合以获得两者的结果

  You could use 
  select * 
  from chat 
  inner join  (
    select max(message_id) max_id, user from (
    select message_id, sender_id as  user
    from chat
    union 
    select message_id, receiver_id 
    from chat) t 
    ) t1 on t1.max_id = chat.message_id
          and chat.sender_id=:sender_id 

为了有效处理此问题,请从以下两个查询开始:

select message_id, sender_id as other_id
from messages
where receiver_id = :user
order by message_id desc;

select message_id, receiver_id as other_id
from messages
where sender_id = :user
order by message_id desc;

可以使用两个索引来优化它们: messages(receiver_id, sender_id, message_id)messages(sender_id, receiver_id, message_id)

您可以union all它们结合在一起,进行排序或汇总以获得最大值:

select m.*
from messages m
where m.message_id in (select max(message_id)
                       from ((select message_id, sender_id as other_id
                              from messages
                              where receiver_id = :user
                              order by message_id desc
                              limit 1
                             ) union all   
                             (select message_id, receiver_id as other_id
                              from messages
                              where sender_id = :user
                              order by message_id desc
                              limit 1
                             )
                            ) mm
                      );

子查询应该能够利用索引(实际上,不需要“其他ID”)。 然后, max()在两行上,并且in应该能够利用(message_id)上的索引。

编辑:

对于修改后的问题,我想不出一种真正有效的方法。 这是一种方法:

select m.*
from messages m
where m.message_id in (select max(m2.message_id)
                       from messages m2
                       where :user in (sender_id, receiver_id)
                       group by (case when sender_id = :user then receiver_id else sender_id end)
                      );

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM