【问题标题】:messages between users: show conversations用户之间的消息:显示对话
【发布时间】:2012-10-24 04:09:13
【问题描述】:

我正在编写一个用于用户通信的消息系统。在收件箱中,我不想向用户显示他/她收到的消息。我只是想展示对话。例如,如果一个用户发送或接收多条消息,那么在收件箱中应该只有与用户的对话(包括最新的消息,无论是书面的还是接收的),当用户点击对话时,他/她可以看到所有过去的消息。

'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' 写的,一条是他收到的..

有人知道如何解决这个问题吗?

【问题讨论】:

  • 所以每发送一条消息在数据库中都有两个条目?

标签: php mysql sql group-by


【解决方案1】:

我在一个月前解决了这个问题。我想您还有一个 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));

【讨论】:

  • 非常感谢您的回答。这很好用,但我得到 date_message 字段的“[BLOB - 25 Bytes]”。我怎样才能从 date_message 字段中提取消息?
  • 发生这种情况是因为不同类型的组 concat 将转换为二进制字段。但是,当您使用 php 获得结果并制作 explode("|",$row['last_message']) 时,这应该不是问题
【解决方案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

例如小提琴http://sqlfiddle.com/#!2/05d191/3/0

【讨论】:

    【解决方案3】:

    假设我们想查看具有特定_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(“通讯员”)和两个用户之间的消息数(“总数”)。

    问候

    【讨论】:

    • 我喜欢你获取通讯作者 ID 的方法,我已经用这个替换了我的答案中更繁琐的案例陈述。
    【解决方案4】:

    您只会收到一条消息,只要消息 (message_id) 是唯一的。当然,如果通信时间较长,您会收到多条消息。

    注意:这里不需要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;
    

    【讨论】:

      猜你喜欢
      • 2019-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-16
      • 2013-08-13
      相关资源
      最近更新 更多