6

我第一次遇到以下查询的问题是该group by子句是在 之前执行的order by

saved.recipe_id列是由生成的整数UNIX_TIMESTAMP()

SELECT
    saved.recipe_id,
    saved.`date`,
    user.user_id
FROM saved
    JOIN user
        ON user.id = saved.user_id
GROUP BY saved.recipe_id
ORDER BY saved.`date` DESC

所以我用子查询和其他 bs 尝试了各种不同的可能解决方案。最后,我最终在join子句中尝试了一些不同的子查询,要求我将表顺序从from子句更改为join子句。我决定尝试以下方法:

SELECT
    saved.recipe_id,
    saved.`date`,
    user.user_id
FROM user
    JOIN saved
        ON user.id = saved.user_id
GROUP BY saved.recipe_id
ORDER BY saved.`date` DESC

出于某种原因,这似乎正确排序,但为什么呢?
此更改如何使我的查询排序比以前更正确?
真的吗?还是只是碰巧针对我提出的测试用例这样做?

4

2 回答 2

12

所以我第一次遇到以下查询的问题是 group by 子句在 order by 之前执行:

这不是问题。这就是 SQL 的定义方式和运行方式。group by创建一组新的行并对这些order by行进行排序。

这里没有订购问题。有一个“对 SQL 的理解”的问题。您order by只是订购查询的结果。这些结果是由 产生的group by,连接的顺序与结果无关。

您正在使用一个名为 Hidden Columns 的 MySQL 扩展。这是当您有一个聚合查询,其select(或havingorder by子句)中的列不属于聚合函数(sum()等)或不属于group by. 这是文档中的引用:

MySQL 扩展了 GROUP BY 的使用,以便选择列表可以引用未在 GROUP BY 子句中命名的非聚合列。这意味着前面的查询在 MySQL 中是合法的。您可以使用此功能通过避免不必要的列排序和分组来获得更好的性能。但是,这主要在每个未在 GROUP BY 中命名的非聚合列中的所有值对于每个组都相同时很有用。服务器可以从每个组中自由选择任何值,因此除非它们相同,否则选择的值是不确定的。此外,从每个组中选择值不会受到添加 ORDER BY 子句的影响。结果集的排序发生在选择值之后,并且 ORDER BY 不会影响服务器选择每个组中的哪些值。

大概,您想要最近的日期和与之关联的用户。以下查询正确且一致地执行您想要的操作:

SELECT saved.recipe_id, max(saved.`date`) as MostRecentDate,
       substring_index(group_concat(user.user_id), ',', 1) as MostRecentUser
FROM user JOIN
     saved
     ON user.id = saved.user_id
GROUP BY saved.recipe_id
ORDER BY max(saved.`date`) DESC;
于 2013-09-12T12:04:57.040 回答
2

据我所知,GROUP BY 总是在 ORDER BY 之前执行。如果您检索不在任何聚合函数中的任何列,则该列的结果将是随机的。您第二次查询的正确顺序是偶然的。

而是saved.date使用MAX(saved.date)

然后,您将从每个单组中获得确定的顺序,然后您将对确定的结果进行排序。

于 2013-09-12T11:34:19.563 回答