【问题标题】:SQL: How to keep rows order with DISTINCT?SQL:如何使用 DISTINCT 保持行顺序?
【发布时间】:2011-08-11 12:55:23
【问题描述】:

以下 SQL 查询:

SELECT messages.id, messages.created_at, comments.created_at FROM messages
LEFT JOIN comments ON comments.message_id = messages.id 
WHERE (messages.id IN (429,443)) 
ORDER BY GREATEST(messages.created_at, comments.created_at) DESC

返回:

 id         messages.created_at     comments.created_at
--------------------------------------------------------
 443                2                       5
 429                1                       4
 443                2                       3

 (I replaced dates with numbers for readability)

只有在我添加DISTINCT 后才能获得每个id

SELECT DISTINCT messages.id FROM messages
LEFT JOIN comments ON comments.message_id = messages.id 
WHERE (messages.id IN (429,443)) 
ORDER BY GREATEST(messages.created_at, comments.created_at) DESC

但是,结果id 值改变了顺序:

id
---
429
443

这可能是什么原因?

我怎样才能保持订单?

【问题讨论】:

  • 我的猜测是 mysql 在找到前两个匹配项并相应地对它们进行排序后停止。很可能最后两个条目首先被找到,因为根据您对 created_at 的使用判断它们是首先插入的。
  • 我不确定,但你真的不知道在 distinct 之后保留了哪些行。我不确定mysql是如何做到的。看到您运行两个查询并包含两个 created_at 列会很有趣。
  • SELECT messages.id, messages.created_at, comments.created_at 所以我们可以看到其他列的值,因为这是您订购的内容。我猜429 的 created_at 比 443 的 created_at 高

标签: mysql sql sql-order-by distinct


【解决方案1】:

distinct 关键字正在做它应该做的事情,每行返回一个具有给定列值的行。 Distinct 不允许您指定 which 将返回这样的行,并且从原始查询中可以清楚地看出,允许这样的排序(id 为 443 的行跟在 id 为 429 的行之后)。

要控制将返回的行,您需要重新编写查询。我将采用的典型解决方案是使用group by,从每个组中选择组列和所需行,效果如下:

SELECT message.id, MAX(message.created_at) FROM message GROUP BY message.id;

如果我需要做更多,我将使用这种查询作为更大查询中的子选择,可能加入 id 字段以从首选行中获取更多字段,或者以特定方式对查询进行排序。

【讨论】:

  • 谢谢。事实上,GROUP BY 似乎是一个合理的方法。
猜你喜欢
  • 2010-09-16
  • 1970-01-01
  • 2010-09-17
  • 1970-01-01
  • 1970-01-01
  • 2020-04-17
相关资源
最近更新 更多