【发布时间】:2020-01-26 20:27:03
【问题描述】:
我不经常使用GROUP BY 子句,但我想我对它的使用规则有一个大致的了解。
我也不会使用各种各样的数据库。
我刚刚对使 GROUP BY 子句“可移植”的规则感兴趣。
我根据一些实验列出了一份清单,但我不太确定它是否全面或正确。 希望有经验的大侠能进来看看。
可移植 GROUP BY 子句的规则
这些规则存在 GROUP BY 子句,
- 如果使用聚合表达式并且不存在显式 GROUP BY 子句,则隐含具有空分组集的 GROUP BY 子句
- SELECT/HAVING/ORDER BY 子句中的非聚合表达式中使用的列必须在 GROUP BY 子句中
- SELECT 子句中的别名表达式不得在 GROUP BY 子句中使用
- GROUP BY 子句可能包含不在 SELECT 子句中的列
- GROUP BY 子句在 HAVING 之前是必需的
对于这些规则,GROUP BY 子句可能存在也可能不存在,
- 任何列可以在 SELECT/HAVING/ORDER BY 子句的聚合表达式中使用
- ORDER BY 子句可能引用 SELECT 子句中的别名聚合表达式
- HAVING 子句不得在 SELECT 子句中引用别名
以下是一些详细说明,
聚合与非聚合表达式
聚合函数是 SUM()、AVG()、MAX() 等函数。
它们从多行中获取值,并将它们聚合为单个值。
聚合表达式聚合来自多行的值。
非聚合表达式每行产生一个值。
别名与非别名表达式
别名表达式具有以下形式,expr AS alias
无别名表达式只是没有AS alias 部分的表达式。
在 SELECT 子句中使用别名表达式
如果使用聚合表达式并且不存在显式 GROUP BY 子句,则隐含具有空分组集的 GROUP BY 子句
以下查询是等价的,
SELECT SUM(myColumn) FROM myTable;SELECT SUM(myColumn) FROM myTable GROUP BY ();
SELECT/HAVING/ORDER BY 子句中的非聚合表达式中使用的列必须在 GROUP BY 子句中
有效查询示例,
SELECT myColumn FROM myTable GROUP BY myColumn;SELECT myColumn + 1 FROM myTable GROUP BY myColumn;SELECT myColumn FROM myTable GROUP BY myColumn, otherColumn ORDER BY otherColumn ASC;SELECT myColumn FROM myTable GROUP BY myColumn, otherColumn ORDER BY otherColumn + 1 ASC;SELECT myColumn FROM myTable GROUP BY myColumn, otherColumn HAVING otherColumn >= 2;SELECT myColumn FROM myTable GROUP BY myColumn, otherColumn HAVING otherColumn + 1 >= 2;
无效查询示例,
SELECT myColumn FROM myTable GROUP BY otherColumn;SELECT myColumn FROM myTable GROUP BY myColumn ORDER BY otherColumn ASC;SELECT myColumn FROM myTable GROUP BY myColumn HAVING otherColumn >= 2;
SELECT 子句中的别名表达式不得在 GROUP BY 子句中使用
无效查询示例,
SELECT myColumn AS x FROM myTable GROUP BY x;SELECT myColumn+otherColumn AS x FROM myTable GROUP BY x;SELECT SUM(myColumn) AS x FROM myTable GROUP BY x;SELECT myColumn+otherColumn AS x FROM myTable GROUP BY x;
有效查询示例,
SELECT myColumn AS x FROM myTable GROUP BY myColumn;SELECT myColumn+otherColumn AS x FROM myTable GROUP BY myColumn+otherColumn;
GROUP BY 子句可能包含不在 SELECT 子句中的列
有效查询示例,
SELECT myColumn FROM myTable GROUP BY myColumn, otherColumn;SELECT myColumn FROM myTable GROUP BY myColumn, otherColumn, myTableId;
GROUP BY 子句在 HAVING 之前是必需的
有效查询示例,
SELECT myColumn FROM myTable GROUP BY myColumn HAVING myColumn >= 2;SELECT myColumn FROM myTable GROUP BY myColumn HAVING SUM(otherColumn) > 3;
无效查询示例,
SELECT 1 FROM myTable HAVING myColumn >= 2;SELECT 1 FROM myTable HAVING SUM(otherColumn) > 3;
任何列可以在 SELECT/HAVING/ORDER BY 子句的聚合表达式中使用
有效查询示例,
SELECT SUM(myColumn+otherColumn) FROM myTable;SELECT SUM(myColumn+otherColumn) FROM myTable GROUP BY otherColumn;SELECT SUM(myColumn+otherColumn) FROM myTable ORDER BY SUM(myColumn+otherColumn) DESC;SELECT SUM(myColumn+otherColumn) FROM myTable GROUP BY otherColumn ORDER BY SUM(myColumn+otherColumn) DESC;SELECT SUM(myColumn+otherColumn) FROM myTable GROUP BY otherColumn HAVING SUM(myColumn+otherColumn) >= 3;
ORDER BY 子句可能在 SELECT 子句中引用别名聚合表达式
有效查询示例,
SELECT SUM(myColumn) AS x FROM myTable ORDER BY x DESC;SELECT SUM(myColumn) AS x FROM myTable GROUP BY otherColumn ORDER BY x DESC;
HAVING 子句不得在 SELECT 子句中引用别名
无效查询示例,
SELECT myColumn AS x FROM myTable GROUP BY myColumn HAVING x >= 2;
我在 DB Fiddle 上试验了 MySQL、PostgreSQL 和 SQLite。
我想知道其他数据库是否禁止某些内容,但我认为这是允许的,因为我只玩过这 3 个。
或者也许(几乎)所有数据库都允许某些东西,但我认为这是被禁止的,因为脑子放屁。
【问题讨论】:
-
你的问题到底是什么?
-
"SELECT/HAVING/ORDER BY 子句中非聚合表达式中使用的列必须在 GROUP BY 子句中" -- 不一定。如果一列“直接”依赖于您分组的列,则不需要聚合它。
-
“任何列都可以在 SELECT/HAVING/ORDER BY 子句的聚合表达式中使用”——不是这样。一些数据库对列施加限制。例如,不能使用 BLOB 或 CLOB 等大值。此外,一些数据库最多将散列截断为 255 个字符。
-
“ORDER BY 子句可能在 SELECT 子句中引用别名聚合表达式”——并非所有数据库都支持这一点。为安全起见,请使用原始列名。
-
“如果使用聚合表达式并且不存在显式的 GROUP BY 子句,则隐含具有空分组集的 GROUP BY 子句”——您需要澄清这一点。如果未指定 GROUP BY 子句,则必须聚合所有列。
标签: sql