假设我有一张植物桌:
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)。
ORDER BY
?答案 0 :(得分:17)
如果您实际选择聚合值而不是表中的列,则结果会更清晰:
SELECT SUM(id) FROM plant ORDER BY SUM(id)
这将返回所有id的总和。这当然是一个无用的例子,因为聚合总是只创建一行,因此不需要排序。你在查询中获得行qith列的原因是因为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 |
+--------+----------+
答案 1 :(得分: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部分省略了列,请不要使用此功能 在小组中不是一成不变的。服务器可以自由返回任何值 从组中,除非所有值都是,否则结果是不确定的 同样的。
More recent versions are a little different
您可以通过避免使用此功能来获得更好的性能 不必要的列排序和分组。但是,这很有用 主要是当每个非聚合列中的所有值都未命名时 GROUP BY对于每个组都是相同的。服务器可以自由选择 每个组中的任何值,因此除非它们相同,否则为值 选择是不确定的。
就个人而言,我不认为不确定是SQL中的一项功能。
答案 2 :(得分:2)
当你使用这样的聚合时,查询会得到一个隐含的组,整个结果就是一个组。
按顺序使用聚合仅在您还有一个分组时才有用,这样您可以在结果中包含多行。