分组
适用于 ✅ 开源版 ✅ 专业版 ✅ 企业版
聚合函数将来自数据组的数据聚合为单个值。形成这些组主要有三种方式
- GROUP BY 子句用于定义聚合数据的组
- 未定义 GROUP BY 子句,这意味着来自 SELECT 语句(或子查询)的所有数据都聚合到单行中
- 所有聚合函数都可以用作窗口函数,在这种情况下,它们将聚合指定窗口的数据
使用 GROUP BY 进行聚合
在存在 GROUP BY 的情况下,SELECT 语句将其 FROM 子句 的输出转换为包含以下内容的新“虚拟”元组集
GROUP BY
子句的列表达式。 在整个数据集中,这些列表达式的值是唯一的。- 对应于
GROUP BY
子句生成的每一行的数据集。 可以使用聚合函数按组聚合此数据集。
使用 GROUP BY
意味着需要在查询的其余部分中遵守一组新的规则
- 逻辑上位于 GROUP BY 之前的子句不受影响。 这些包括例如 FROM 和 WHERE
- 所有其他子句(例如 HAVING、WINDOW、SELECT 或 ORDER BY)现在只能引用从
GROUP BY
子句中的表达式构建的表达式,或者对任何其他表达式的聚合
一个例子
SELECT AUTHOR_ID, count(*) FROM BOOK GROUP BY AUTHOR_ID;
create.select(BOOK.AUTHOR_ID, count()) .from(BOOK) .groupBy(BOOK.AUTHOR_ID).fetch();
产生
+-----------+-------+ | AUTHOR_ID | count | +-----------+-------+ | 1 | 2 | | 2 | 2 | +-----------+-------+
根据 GROUP BY
施加的规则,例如,不可能投影 BOOK.TITLE
列,因为它不是按作者定义的。 一位作者写了很多书,所以我们不知道 BOOK.TITLE
应该意味着什么。 只有聚合,例如 LISTAGG 或 ARRAY_AGG 可以引用 BOOK.TITLE
作为参数。
不使用 GROUP BY 进行聚合
在没有 GROUP BY 的情况下,SELECT 语句的任何子句(例如 HAVING、WINDOW、SELECT 或 ORDER BY)中包含至少一个聚合函数,则会将整个数据聚合到单行中。 有一个隐含的“空分组”,即没有 GROUP BY
列的分组。 这两个是同一件事
SELECT count(*) FROM BOOK; SELECT count(*) FROM BOOK GROUP BY ();
有关此空 GROUP BY
语法的更多详细信息,另请参见 GROUPING SETS。
例如,使用我们的示例数据库,其中包含 4 本 ID 为 1-4 的书籍,我们可以编写
SELECT count(*), sum(ID) FROM BOOK
create.select(count(), sum(BOOK.ID)) .from(BOOK).fetch();
产生
+----------+---------+ | count(*) | sum(ID) | +----------+---------+ | 4 | 10 | +----------+---------+
FROM 子句中表中的其他任何列都不能被 SELECT 子句投影,因为它们没有为此单个组定义。 例如,未为所有书籍的聚合值定义特定的 BOOK.TITLE
。 只有聚合,例如 LISTAGG 或 ARRAY_AGG 可以引用 BOOK.TITLE
作为参数。
但是,允许使用任何组件不依赖于组内容的表达式。 例如,可以像这样组合聚合函数和常量表达式
SELECT count(*) + sum(ID) + 1 FROM BOOK
create.select(count().plus(sum(BOOK.ID)).plus(1)) .from(BOOK).fetch();
产生
+------+ | plus | +------+ | 15 | +------+
反馈
您对此页面有任何反馈吗? 我们很乐意听到!