在 MySQL(消息系统)中返回多个收件人姓名

Posted

技术标签:

【中文标题】在 MySQL(消息系统)中返回多个收件人姓名【英文标题】:Returning multiple recipients names in MySQL (messaging system) 【发布时间】:2011-04-12 19:27:04 【问题描述】:

我正在创建一个类似于 iPhone SMS 系统的多收件人线程消息系统(其中收件箱和发件箱合并为一个显示,两个用户之间只能存在一个线程)。

使用发件人列(例如“11”)和收件人列(例如“,13,10,15,20”)存储消息。为了存储多个收件人,我用逗号将它们分开,并使用 "%" + ",$userid," + "#" 调用查询该字段。这样做的问题是它弄乱了将接收者连接到用户表(具有用户名)的 LEFT JOIN。

这是我当前的查询:

$sql = 
  "SELECT DISTINCT CASE 
   WHEN $userid != senderid THEN senderid ELSE recipients END someid,   
   CASE WHEN 13 != senderid THEN senders.username ELSE receivers.username END somename,
   messages.body, 
   messages.time 
   FROM messages 
   LEFT JOIN users AS senders ON messages.senderid = senders.id
   LEFT JOIN users AS receivers ON messages.recipients = receivers.id
   WHERE messages.recipients = '#' + ',$userid,' + '#'
   OR messages.senderid = $userid
   ORDER BY messages.time";

这是我想做的:

如果收件人中只有一个收件人 id(内容看起来像“,id”,则删除 id 周围的逗号以找到发件人名称(LEFT JOIN users AS receivers ON messages.recipients(WITHOUT COMMAS ) = receivers.id。

如果收件人中有多个收件人 id(内容看起来像“,id,id2,id3”等),则以某种方式提取与该 ID 对应的所有名称并将结果存储为类似于如下:sendername = "Name1, Name2, Name3";.

有人知道我将如何处理这个问题吗?也许是子查询?非常感谢您的帮助。

【问题讨论】:

【参考方案1】:

第一。而不是:

WHERE messages.recipients = '#' + ',$userid,' + '#'

你可以去掉开始和结束的逗号并使用:

WHERE FIND_IN_SET($userid, messages.recipients) > 0

所以你也可以为 LEFT JOIN 设置这个条件:

LEFT JOIN users AS receivers
  ON FIND_IN_SET(receivers.id, messages.recipients) > 0

然后按消息分组并将名称与GROUP_CONCAT() 连接起来。

类似这样的:

  SELECT senders.name AS senderName
       , messages.body
       , messages.time 
       , GROUP_CONCAT( receivers.name
                       ORDER BY receivers.id
                       SEPARATOR ','
                     )
         AS receiversNames
  FROM messages 
    LEFT JOIN users AS senders
      ON messages.senderid = senders.id
    LEFT JOIN users AS receivers
      ON FIND_IN_SET(receivers.id, messages.recipients) > 0
  GROUP BY messages.id
  ORDER BY messages.time

将为您提供所有邮件,其中发件人姓名和收件人姓名连接在一起。

我猜每条消息都恰好有 1 个(或零个)发件人。如果没有,并且某些邮件的发件人超过 1 个,那么您可能需要编辑 GROUP BY

警告:当表中有很多行时,这种类型的查询可能会很慢(甚至非常慢)。 messages.recipients 上不能使用索引,因此会减慢查询速度。因此,您现在最好考虑使用MessageRecipient 中间表规范化您的结构的选项。

【讨论】:

这看起来很棒,非常感谢。试着出去,我会回复你的! ypercube,我现在正在阅读规范化,但您的意思是创建一个 MessageRecipient 表,您基本上可以在其中“标记”用户到消息? 是的,因此您的 messages.recipients 字段将被该表中的许多行替换(消息中的每个收件人一个) 这是一个更好的结构吗?我标准化了我的数据库。 pastebin.com/UGdKsx14 是的。 messages_recipients 可以有一个复合主键 (messageid, userid)

以上是关于在 MySQL(消息系统)中返回多个收件人姓名的主要内容,如果未能解决你的问题,请参考以下文章

将多个收件人电子邮件和姓名附加到 EmailMultiAlternatives

MYSQL在一个语句中多对多选择(聊天,最新消息,用户名)

消息总线:发件人必须等待来自多个收件人的确认

使用 Facebook API 向多个收件人发送消息

如何将消息发送给多个收件人

Mandrill 通过 REST API 作为单独的消息发送给多个人