[英]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.