【问题标题】:First order by, then Group by先排序,然后分组
【发布时间】:2016-10-15 10:53:23
【问题描述】:

我有一个包含消息的表(person_id、message、conversation_id、created_at)

我想在每个对话中获取最新消息。我尝试过使用子查询,但它似乎忽略了子查询中的 orderby:

SELECT sub.* FROM 
      (SELECT * FROM messages ORDER BY created_at DESC) AS sub
GROUP BY sub.conversation_id

在这个 SQLfiddle 中尝试一下。

还有其他方法可以获得正确的结果吗?

http://sqlfiddle.com/#!9/12739/1

【问题讨论】:

标签: mysql sql sql-order-by


【解决方案1】:

如果您想要每个对话的所有最新消息,您可以在选择的组中使用 where in

SELECT messages.* 
FROM messages 
WHERE (messages.created_at, messages.conversation_id) in 
  (SELECT max(created_at) , conversation_id
     FROM messages messages
     Group by conversation_id);

【讨论】:

  • 谢谢!这是最优化的方式吗?
  • 另一种方法是在同一个表上进行内部联接,按 .. 分组。可能 asnwer 中的查询是最优化的 ..但结果可能取决于表的实际人口 ..
【解决方案2】:

试试这个方法:

SELECT m1.*
FROM messages AS m1
JOIN (
   SELECT conversation_id, MAX(created_at) AS created_at
   FROM messages
   GROUP BY conversation_id
) AS m2 ON m1.conversation_id = m2.conversation_id AND m1.created_at = m2.created_at

【讨论】:

    【解决方案3】:

    无法在 sqlfiddle 上对此进行测试,它不适合我:

    SELECT m1.* 
      FROM messages m1
     WHERE m1.created_at =
          (SELECT max(created_at) 
             FROM messages m2
            where m1.conversation_id=m2.conversation_id)
    

    【讨论】:

      【解决方案4】:

      您可以使用选择列表中的相关子查询来执行此操作,也可以使用来自列表中的子查询连接回您的主表。

      相关子查询:

      SELECT DISTINCT m1.conversation_id, (SELECT * FROM messages m2 WHERE m2.conversation_id=m1.conversation_id ORDER BY created_at DESC LIMIT 1)
      FROM messages m1
      

      from 子句中的子查询:

      SELECT m1.*
      FROM messages as m1
      JOIN (
         SELECT conversation_id, max(created_at) AS max_created_at
         FROM messages
         GROUP BY conversation_id
      ) m2 on m1.conversation_id = m2.conversation_id and m1.created_at = m2.max_created_at
      

      这两种方法的区别在于相关子查询将始终为每个对话 id 返回 1 条记录。如果 2 条记录具有相同的 created_at 值,则第二条记录可能会在每个对话中返回超过 1 条记录。如果有一个自动递增的 id 字段唯一标识每条消息,那么您可以使用此字段的最大值而不是 created at 字段来解决此潜在问题。

      【讨论】:

        猜你喜欢
        • 2016-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-23
        • 2012-10-04
        • 1970-01-01
        • 2018-12-07
        • 1970-01-01
        相关资源
        最近更新 更多