我正在编写用于用户通信的消息系统。在收件箱中,我不想向用户显示他/她收到的消息。我只想展示对话。举例来说,如果一个用户发送或接收多个消息,则在收件箱中应该只与用户进行对话(包括最新消息,无论是写入还是接收),并且当用户点击对话时他/她可以看到所有过去的消息。
'messages'的表结构(简化)如下:
message_id
user_id_sender
user_id_recipient
message
现在问题是消息保存在数据库中,每个行都是一条消息,所以我必须以某种方式对这些消息进行分组。
我想出的select语句如下:
SELECT * FROM messages
WHERE user_id_sender = 1 OR user_id_recipient = 1
GROUP BY user_id_sender
但是现在我显然收到了两条消息,因为一条消息是由用户'1'写的,另一封是他收到的消息。
有人知道如何解决这个问题吗?
答案 0 :(得分:2)
假设message_id是升序的(即更高的ID用于以后的消息)。 @user_id
只是您正在查看的收件箱user_id
的占位符。我已经使用了Andrea的诀窍来简明地获得other_recipient_id
。
Select
mm.other_recipient_id,
m.*
From (
Select
user_id_sender + user_id_recipient - @user_id as other_recipient_id,
Max(message_id) as message_id
From
messages
Where
user_id_sender = @user_id Or
user_id_recipient = @user_id
Group By
user_id_sender + user_id_recipient - @user_id
) mm
Inner Join
messages m
On
mm.message_id = m.message_id
答案 1 :(得分:2)
我在一个月前解决了这个问题。我想你还有一个date
字段。此查询为您提供结构良好的结果,其中包含最后一条消息和最后一条消息的日期。
$qry = 'SELECT
CONCAT(GREATEST(user_id_sender,user_id_recipient)," ",LEAST(user_id_sender,user_id_recipient)) AS thread,
MAX(CONCAT(date,"|",message)) as date_message,
MAX(date) AS last_message,
messages.*
FROM messages
WHERE user_id_sender= ? || user_id_recipient=? GROUP BY thread ORDER BY last_message DESC';
$rows = $db->fetchAll($qry, Array($current_user_id,$current_user_id));
答案 2 :(得分:0)
只要消息(message_id
)是唯一的,您只能收到一条消息。当然,如果进行更长时间的通信,您将收到多条消息。
N.B。:此处您不需要group by
,因为这仅用于汇总列,例如:
SELECT user_id_sender, sum(*) FROM messages
GROUP BY user_id_sender;
您可以获得每个用户发送的邮件总数。
所以,如果你想看到两个用户之间的沟通:
SELECT * FROM messages
WHERE user_id_sender = 1 OR user_id_recipient = 1;
如果您也存储时间戳,可以进一步限制,例如message_time
或限制显示的消息数量:
select * from ... limit 10;
答案 3 :(得分:0)
假设我们希望看到具有特定_ ID _的用户的对话,则此查询可能很有用:
SELECT (user_id_sender + user_id_recipient) - _ID_ AS correspondent, COUNT(*) AS total
FROM messages
WHERE user_id_sender = _ID_ OR user_id_recipient = _ID_
GROUP BY (user_id_sender + user_id_recipient)
生成的查询返回对话的其他用户的ID(“通讯员”)以及两个用户之间的消息数(“总数”)。
此致