聚集函数 从一组输入值计算出一个单一的结果。 内置的通用聚集函数列在 Table 9.62 中, 而统计聚集列在 Table 9.63 中。 内置的分组内有序集聚集函数列在 Table 9.64 中, 而内置的分组内假想集聚集列在 Table 9.65 中。 与聚集函数密切相关的分组操作列在 Table 9.66 中。 聚集函数的特殊语法考量在 Section 4.2.7 中解释。 更多入门信息请参见 Section 2.7。
支持 部分模式 的聚集函数有资格参与各种优化, 例如并行聚集。
虽然下面所有的聚集都接受一个可选的
ORDER BY
子句
(如
Section 4.2.7
中概括的那样),
但这个子句只被加到那些其输出受排序影响的聚集上。
Table 9.62. 通用聚集函数
函数 说明 | 部分模式 |
|---|---|
从非空输入值中返回一个任意的值。 | Yes |
把所有输入值 (包括空值) 收集到一个数组中。 | Yes |
把所有输入数组连接成一个高一维的数组。 (这些输入必须都具有相同的维数, 并且不能为空或空值。) | Yes |
|
计算所有非空输入值的平均 (算术平均)。 | Yes |
计算所有非空输入值的按位与。 | Yes |
计算所有非空输入值的按位或。 | Yes |
计算所有非空输入值的按位异或。 它可以作为一组无序值的校验和。 | Yes |
如果所有非空输入值都为真则返回真, 否则返回假。 | Yes |
|
如果任何非空输入值为真则返回真, 否则返回假。 | Yes |
|
计算输入行的数量。 | Yes |
计算输入值非空的输入行的数量。 | Yes |
|
这是 SQL
标准中与
| Yes |
把所有输入值
(包括空值)
收集到一个 JSON
数组中。
值按照
| No |
把所有输入值
(跳过空值)
收集到一个 JSON
数组中。
值按照
| No |
行为与
| No |
行为类似于
| No |
把所有键/值对收集到一个 JSON
对象中。
键参数被强制转换为文本;
值参数按照
| No |
把所有键/值对收集到一个 JSON
对象中。
键参数被强制转换为文本;
值参数按照
| No |
把所有键/值对收集到一个 JSON
对象中。
键参数被强制转换为文本;
值参数按照
| No |
把所有键/值对收集到一个 JSON
对象中。
键参数被强制转换为文本;
值参数按照
| No |
计算非空输入值的最大值。
可用于任何数值、
字符串、
日期/时间或枚举类型,
以及
| Yes |
计算非空输入值的最小值。
可用于任何数值、
字符串、
日期/时间或枚举类型,
以及
| Yes |
计算非空输入值的并集。 | No |
计算非空输入值的交集。 | No |
把非空输入值串接成一个字符串。
第一个值之后的每个值前面都会加上相应的
| Yes |
|
计算非空输入值的总和。 | Yes |
串接非空的 XML 输入值 (参见 Section 9.15.1.8)。 | No |
应当注意,
除了
count
之外,
这些函数在没有选中任何行时都会返回一个空值。
特别是,
对于零行,
sum
返回的是空而非人们可能期望的零,
而当没有输入行时
array_agg
返回的是空而非一个空数组。
必要时可以使用
coalesce
函数把零或空数组替换掉空值。
聚集函数
array_agg、
json_agg、
jsonb_agg、
json_agg_strict、
jsonb_agg_strict、
json_object_agg、
jsonb_object_agg、
json_object_agg_strict、
jsonb_object_agg_strict、
json_object_agg_unique、
jsonb_object_agg_unique、
json_object_agg_unique_strict、
jsonb_object_agg_unique_strict、
string_agg
和
xmlagg,
以及类似的用户定义聚集函数,
产生的结果值会根据输入值的顺序而有意义地不同。
这种顺序默认是不确定的,
但可以通过在聚集调用内写一个
ORDER BY
子句来控制,
如
Section 4.2.7
所示。
或者,
从一个已排序的子查询中提供输入值通常也能奏效。
例如:
SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab;
注意, 如果外层查询层级包含额外的处理 (例如一个连接), 这种方法可能失败, 因为那可能导致子查询的输出在聚集被计算之前被重新排序。
布尔聚集
bool_and 和
bool_or
对应于标准 SQL
的聚集
every 和
any
或
some。
PostgreSQL
支持
every,
但不支持
any
或
some,
因为标准语法中内建了一种歧义:
SELECT b1 = ANY((SELECT b2 FROM t2 ...)) FROM t1 ...;
在这里,
如果子查询返回带布尔值的一行,
那么
ANY
既可以被理解为引入一个子查询,
也可以被理解为是一个聚集函数。
因此这些聚集不能被赋予标准的名字。
习惯于使用其他 SQL
数据库管理系统的用户,
可能会对把
count
聚集应用到整张表上的性能感到失望。
一条这样的查询:
SELECT count(*) FROM sometable;
将需要与表的尺寸成比例的工作量: PostgreSQL 将需要扫描整张表, 或者扫描一个包含该表中所有行的索引的全部内容。
Table 9.63
展示了通常用于统计分析的聚集函数。
(它们被单独列出只是为了避免把更常用的聚集的列表弄乱。)
展示为接受
numeric_type
的函数可用于
smallint、
integer、
bigint、
numeric、
real
和
double precision
这些类型中的全部。
描述中提到
N
的地方,
它表示所有输入表达式都非空的输入行的数量。
在所有情况下,
如果计算是没有意义的,
例如
N
为零时,
都会返回空。
Table 9.63. 用于统计的聚集函数
Table 9.64
展示了一些使用
有序集聚集
语法的聚集函数。
这些函数有时被称为
“逆分布”函数。
它们的聚合输入由
ORDER BY
引入,
而且它们还可以接受一个不被聚合、
只被计算一次的
直接参数。
所有这些函数都会忽略其聚合输入中的空值。
对于那些接受
fraction
参数的函数,
分数值必须介于 0 和 1
之间;
否则会抛出一个错误。
然而,
一个空的
fraction
值只会产生一个空结果。
Table 9.64. 有序集聚集函数
Table 9.65
中列出的每一个
“假想集”聚集,
都与
Section 9.22
中定义的一个同名窗口函数相关联。
在每种情况下,
聚集的结果就是相关的窗口函数,
对于由
args
构造的
“假想”行,
本来会返回的值
(前提是这样的行被加入到了由
sorted_args
表示的已排序行组中)。
对于这些函数中的每一个,
在
args
中给出的直接参数列表,
都必须与
sorted_args
中给出的聚合参数在数量和类型上相匹配。
与大多数内置聚集不同,
这些聚集不是严格的,
也就是说,
它们不会丢弃包含空值的输入行。
空值按照
ORDER BY
子句中指定的规则排序。
Table 9.65. 假想集聚集函数
Table 9.66. 分组操作
Table 9.66
中展示的分组操作与分组集一起使用
(参见
Section 7.2.4)
来区分结果行。
GROUPING
函数的参数实际上不会被求值,
但它们必须与相关查询层级的
GROUP BY
子句中给出的表达式精确匹配。
例如:
=>SELECT * FROM items_sold;make | model | sales -------+-------+------- Foo | GT | 10 Foo | Tour | 20 Bar | City | 15 Bar | Sport | 5 (4 rows)=>SELECT make, model, GROUPING(make,model), sum(sales) FROM items_sold GROUP BY ROLLUP(make,model);make | model | grouping | sum -------+-------+----------+----- Foo | GT | 0 | 10 Foo | Tour | 0 | 20 Bar | City | 0 | 15 Bar | Sport | 0 | 5 Foo | | 1 | 30 Bar | | 1 | 20 | | 3 | 50 (7 rows)
这里,
前四行中的
grouping
值
0
表明它们是在两个分组列上都正常分组的。
值
1
表明在倒数第二和第三行中
model
没有被分组,
而值
3
表明在最后一行中
make 和
model
都没有被分组
(因此最后一行是对所有输入行的一个聚合)。