聚合函数在 ORDER BY 子句中可以做什么?

问题描述 投票:0回答:4

假设我有一张植物桌:

id fruit
1  banana
2  apple
3  orange

这些我都能做

SELECT * FROM plant ORDER BY id;
SELECT * FROM plant ORDER BY fruit DESC;

这做了显而易见的事情。

但是我被这个咬了,这个有什么作用呢?

SELECT * FROM plant ORDER BY SUM(id);
SELECT * FROM plant ORDER BY COUNT(fruit);
SELECT * FROM plant ORDER BY COUNT(*);
SELECT * FROM plant ORDER BY SUM(1) DESC;

所有这些都只返回第一行(id = 1)。

  1. 底层发生了什么?
  2. 聚合函数在哪些场景会派上用场
    ORDER BY
mysql sql sql-order-by aggregate-functions
4个回答
24
投票

如果您实际选择聚合值而不是表中的列,您的结果会更清晰:

SELECT SUM(id) FROM plant ORDER BY SUM(id)

这将返回所有 id 的总和。这当然是一个无用的示例,因为聚合始终只会创建一行,因此不需要排序。在查询中得到第 qi 列的行的原因是 MySQL 选择一行,不是随机的,也不是确定性的。在您的情况下,它恰好是表中的第一列,但其他人可能会根据存储引擎、主键等获得另一行。因此,仅在 ORDER BY 子句中进行聚合并不是很有用。

您通常想要做的是按某个字段进行分组,然后以某种方式对结果集进行排序:

SELECT fruit, COUNT(*)
FROM plant
GROUP BY fruit
ORDER BY COUNT(*)

现在这是一个更有趣的查询!这将为您提供每种水果的一行以及该水果的总数。尝试添加更多的苹果,排序实际上就会开始有意义:

完整表格:

+----+--------+
| id | fruit  |
+----+--------+
|  1 | banana |
|  2 | apple  |
|  3 | orange |
|  4 | apple  |
|  5 | apple  |
|  6 | banana |
+----+--------+

上面的查询:

+--------+----------+
| fruit  | COUNT(*) |
+--------+----------+
| orange |        1 |
| banana |        2 |
| apple  |        3 |
+--------+----------+

4
投票

所有这些查询都会在任何符合 SQL 标准的 SQL 平台上给你带来语法错误。

SELECT * FROM plant ORDER BY SUM(id);
SELECT * FROM plant ORDER BY COUNT(fruit);
SELECT * FROM plant ORDER BY COUNT(*);
SELECT * FROM plant ORDER BY SUM(1) DESC;

例如,在 PostgreSQL 上,所有这些查询都会引发相同的错误。

错误:列“plant.id”必须出现在 GROUP BY 子句中或者是 用于聚合函数

这意味着您正在使用域聚合函数而不使用 GROUP BY。 SQL Server 和 Oracle 返回类似的错误消息。

MySQL 的 GROUP BY 已知在多个方面存在问题,至少就标准行为而言是这样。但你发布的查询对我来说是一种新的破坏行为,所以+1。

与其试图理解它在幕后的作用,不如学习编写标准的 GROUP BY 查询。据我所知,MySQL 正确处理标准 GROUP BY 语句。

早期版本的 MySQL 文档警告您有关 GROUP BY 和隐藏列的信息。 (我没有参考资料,但这篇文章到处都被引用。)

如果您在 GROUP BY 部分中省略了列,请勿使用此功能 在群体中不是恒定的。服务器可以自由返回任何值 来自该组,因此结果是不确定的,除非所有值都是 一样的。

最近的版本有点不同

您可以使用此功能通过避免 不必要的列排序和分组。不过,这很有用 主要是当每个非聚合列中的所有值都未命名时 每个组的 GROUP BY 都是相同的。服务器可自由选择 每个组中的任何值,因此除非它们相同,否则这些值 选择是不确定的。

就个人而言,我不认为不确定是 SQL 中的功能。


2
投票
  1. 当您使用这样的聚合时,查询将获得一个隐式组,其中整个结果是一个组。

  2. 仅当您还具有分组依据时,在 order by 中使用聚合才有用,这样结果中就可以有多于一行。


0
投票

如果您在使用动态查询执行表旋转时想要特定的列顺序,也可以在 order by 子句中使用聚合函数。如果透视列和排序列不同,您可以在 order by 子句中使用 Max(OrderingCol) 进行相应排序。

© www.soinside.com 2019 - 2024. All rights reserved.