9.15. 聚集函数

聚集函数 从一套输入值里计算一个结果。 Table 9-37 显示了内建聚集函数。 聚集函数的特殊语法在 Section 4.2.7里解释。请参考 Part I 获取附加的介绍性信息。

Table 9-37. 聚集函数

函数参数类型返回类型描述
avg(expression) 所有输入值的均值(算术平均) smallint, integer, bigint, real, double precision, numeric, 或 interval. 对于任何整数类型输入,结果都是 numeric 类型。 对于任何浮点输入,结果都是 double precision 类型。 否则和输入数据类型相同。 所有输入值的平均(算术平均)。
bit_and(expression) smallint, integer, bigint, 或者 bit 和参数数据类型相同 所有非空输入值的按位 AND (与),如果没有,则为空
bit_or(expression) smallint, integer, bigint, 或者 bit 和参数数据类型相同 所有非空输入值的按位 OR (或),如果没有,则为空
bool_and(expression) bool bool 如果所有输入值都是真,则为真,否则为假
bool_or(expression) bool bool 如果至少有一个输入值为真,则为着,否则为假
count(*) bigint输入值的个数
count(expression)任意bigint 计算那些 expression 非 NULL 的输入的个数。
every(expression) bool bool 等效于 bool_and
max(expression)任何数值,字串或者日期/时间类型与参数同类型所有输入值中, expression 的最大值
min(expression)任何数值,字串或者日期/时间类型与参数同类型所有输入值中, expression 的最小值
stddev(expression) smallint, integer, bigint, real, double precision, 或 numeric. 浮点数参数时是double precision, 否则 numeric输入值的标准采样偏差(sample standard deviation)
sum(expression) smallint, integer, bigint, real, double precision, numeric, 或者 interval smallintinteger输入 输出类型为 bigint。对于bigint输入输出类型为 numeric, 浮点数输入的结果是 double precision。 否则和输入数据类型相同。 所有输入值的 expression 的总和
variance(expression) smallint, integer, bigint, real, double precision, 或者 numeric. 浮点数参数是 double precision, 否则是 numeric输出值的采样方差(标准采样偏差的平方)。

请注意除了 count 以外, 这些函数在没有选中行时返回 NULL。 尤其要指出的是对零输入行进行 sum 将返回 NULL, 而不是我们预期的零。 必要时可以用 coalesce 把 NULL 替换成零。

注意: 布尔聚集 bool_andbool_or 对应标准的 SQL 聚集 everyany 或者 some。对于 anysome, 标准语法里面似乎有些内置的歧义:

SELECT b1 = ANY((SELECT b2 FROM t2 ...)) FROM t1 ...;

这里的 ANY 既可以被认为是引出一个子查询,也可以认为是一个聚集(如果查询表达式返回 1 行电话)。 因此标准的名字无法用于这些聚集。

注意: 习惯了使用其它 RDBMS 产品的用户可能会对 PostgreSQL 里面的一些聚集函数的性能特点感到奇怪,特别是对整个表进行聚集的时候 (换句话说,不声明 WHERE 子句的时候)。 比如,一个下面这样的查询:

SELECT min(col) from sometable;

将会被 PostgreSQL 以对整个表进行顺序扫描的形式进行执行。 而其它数据库系统可能会把这样的查询优化成使用某个字段上的索引的方式(如果有索引的话)。 在 PostgreSQL 里类似的还有, 如果对整个表进行处理的话,聚集函数 max()count() 总是要求一次顺序扫描。

PostgreSQL 无法很容易地实现这样的 优化,因为它还允许用户定义的聚集查询。因为 min()max(),和 count() 都是使用一个聚集函数的普通 API 定义的,因此在某些场合里, 这些函数的执行并不需要规定"特殊转换"

幸运的是,对于 min()max(), 我们有些简单的方法来绕开。比如下面显示的查询就等效于上面的查询, 但是,如果在目标字段上有索引,那么它可以利用一个 B+ 树索引来优化。

SELECT col from sometable ORDER BY col ASC LIMIT 1;

类似的查询(通过把上面查询的 ASC 替换成 DESC 就行了)也可以用在 max() 的地方。

糟糕的是,在对全表操作的时候,没有类似简单的查询可以用于改进 count() 的性能。