【问题标题】:MySQL GROUP BY / ORDER BY issue with flat messages table / threadsMySQL GROUP BY / ORDER BY 问题与平面消息表/线程
【发布时间】:2011-06-24 18:29:10
【问题描述】:

好的,我正在尝试以此为基础,但还没有完全确定:GROUP BY and ORDER BY

基本上,想要查询在当前登录用户和任何其他用户之间的每个“线程”中查找最新消息,但通过一个平面(非“线程”)消息表:

messages {
  id,
  from_uid,
  to_uid,
  message_text,
  time_added
}

假设当前用户的 uid 为“1”,每个“线程”中的最新消息可能是来自那个用户,或者那个用户(另一个方始终由 thread_recipient 表示):

SELECT a.*,thread_recipient
  FROM messages a
  JOIN (SELECT IF(from_uid = '1',to_uid,from_uid) AS thread_recipient,
               MAX(time_added) AS recency
          FROM messages 
         WHERE (from_uid = '1' OR to_uid = '1')
      GROUP BY thread_recipient) b ON thread_recipient = (IF(a.from_uid = '1',a.to_uid,a.from_uid))
                             AND b.recency = a.time_added
 ORDER BY a.time_added DESC

但我担心这不会正常工作,可能同时发送的消息最终会返回给错误的用户?

我的 WHERE 条件是否放错地方了?

非常感谢任何智慧。

【问题讨论】:

    标签: mysql sql group-by sql-order-by messaging


    【解决方案1】:

    这里有个思路:取下面两个查询的UNION,然后得到 结果的最大日期。

    SELECT id,to_uid AS other_party,time_added FROM messages WHERE from_uid = '1'
    
    SELECT id,from_uid AS other_party,time_added FROM messages WHERE to_uid = '1'
    

    当您执行以下操作时:

    SELECT MAX(time_added),other_party
    FROM (SELECT id,to_uid AS other_party,time_added FROM messages WHERE from_uid = '1'
          UNION
          SELECT id,from_uid AS other_party,time_added FROM messages WHERE to_uid = '1'
         ) MyMessages
    GROUP BY other_party
    

    您将获得与发送到的消息相关联的最近时间 用户“1”对应的每个人。然后就可以加入 结果到原始消息表中以获得您想要的:

    SELECT Messages.*
    FROM (SELECT MAX(time_added) AS MaxTime,other_party
          FROM (SELECT id,to_uid AS other_party,time_added FROM messages WHERE from_uid = '1'
                UNION
                SELECT id,from_uid AS other_party,time_added FROM messages WHERE to_uid = '1'
               ) MyMessages
          GROUP BY other_party
         )
         JOIN Messages
         ON (Messages.time_added = MyMessages.MaxTime AND
              (Messages.to_uid = MyMessages.other_party AND Messages.from_uid = '1' OR
               Messages.from_uid = MyMessages.other_party AND Messages.to_uid = '1')
            )
    

    【讨论】:

      【解决方案2】:

      试试这个 - 我认为它可以更简单有效地为您提供所需的内容。

      SELECT latest_time = MAX(a.time_added, b.time_added)
      FROM messages a, messages b
      
      LEFT JOIN messages a1
          ON a1.from_uid = a.from_id
      
      -- find the case where the following doesn't exist
      -- so you know there is nothing after b1
      LEFT JOIN messages a2
          ON a2.from_uid = a.from_id
          AND a2.time_added > a1.time_added
      
      LEFT JOIN messages b1
          ON b1.to_uid = b.to_id
      
      LEFT JOIN messages b2
          ON b2.to_uid = b.to_id
          AND b2.time_added > b1.time_added
      
      WHERE a.from_id = '1'
          AND b.to_id = '1'
          AND c1.id IS NULL
          AND c2.id IS NULL
      
      ORDER BY a.time_added DESC
      

      【讨论】:

      • 如果我理解正确的话,messages表中没有thread_recipient列,这就是问题的本质。消息有 from 和 to,但是在执行此查询时,我们从用户 '1' 的角度来看,并希望通过 thread_recipient 调用“另一个人”。
      • 我认为这很有效。只要线程中的用户“1”至少发送了一条消息,它肯定可以工作。但我想也许我已经在这个问题上花了太长时间了;提问者应该能够使用我们的两个答案之一来使事情发生! +1
      【解决方案3】:

      好的,在 cmets 之后 - 如果 id 是自动增量,则使用它而不是消息时间。但是你有适当的条件来确保消息不会被传递给错误的人。

      【讨论】:

      • 他想要最新的消息,并且他想要发送给/来自他对应的每个人的最新消息。
      • ...您仍然没有为每个通讯员返回一条消息,这就是问题的重点。
      猜你喜欢
      • 1970-01-01
      • 2017-02-11
      • 1970-01-01
      • 2013-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多