↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1 / 7.0 / 6.5 / 6.4
历史版本PostgreSQL 7.1 已于 2006 年 4 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

第 16 章 扩展 SQL:聚合

Postgres 中的聚合函数被表示为状态值和 状态转换函数。也就是说,聚合可以按照每当处理一个输入项就被修改的状态来定义。要定义一个新的聚合函数,需要为状态值选择一种 数据类型、为状态选择一个初始值,以及一个状态转换函数。状态转换函数只是一个普通函数,也可以在聚合上下文之外使用。还可以指定一个最终函数,以防聚合的期望输出与需要保存在运行状态值中的数据不同。

因此,除了聚合的用户所能看到的输入和结果数据类型之外,还有一个内部的状态值数据类型,它可能与输入和结果类型都不同。

如果我们定义一个不使用最终函数的聚合,得到的就是一个对每行列值计算运行函数的聚合。"Sum" 就是这类聚合的一个例子。"Sum" 从零开始,总是把当前行的值加到它的运行总和上。例如,如果我们想让 Sum 聚合作用于复数的数据类型,我们只需要该数据类型的加法函数。聚合定义是:

CREATE AGGREGATE complex_sum (
    sfunc = complex_add,
    basetype = complex,
    stype = complex,
    initcond = '(0,0)'
);

SELECT complex_sum(a) FROM test_complex;

         +------------+
         |complex_sum |
         +------------+
         |(34,53.9)   |
         +------------+
   

(实践中我们只会把该聚合命名为 "sum",让 Postgres 自行判断对复数列应用哪种 sum。)

如果没有非空的输入值,上面 "Sum" 的定义将返回零(初始状态条件)。也许我们希望在这种情形下改为返回 NULL——SQL92 期望 "Sum" 表现出那样的行为。要做到这一点,只需省略 "initcond" 子句,使初始状态条件为 NULL。通常这意味着 sfunc 需要检查 NULL 的状态条件输入,但对于 "Sum" 以及 "Max"、"Min" 等一些简单聚合,只需把第一个非空输入值插入状态变量,然后从第二个非空输入值开始应用转换函数就足够了。当初始条件为 NULL 且转换函数被标记为 "strict"(即不对 NULL 输入调用)时, Postgres 会自动完成这一工作。

"strict" 转换函数的另一项默认行为是:每当遇到 NULL 输入值时,先前的状态值保持不变。这样, NULL 值就被忽略了。如果你需要 NULL 输入有其他行为,只需把转换函数定义为非 strict,并让它测试 NULL 输入并做任何需要的处理。

"Average"(平均值)是聚合的一个更复杂的例子。它需要两个运行状态: 输入的总和以及输入的数量。最终结果通过这两个量相除得到。平均值 通常用二元数组作为转换状态值来实现。例如, avg(float8) 的内置实现如下所示:

CREATE AGGREGATE avg (
    sfunc = float8_accum,
    basetype = float8,
    stype = float8[],
    finalfunc = float8_avg,
    initcond = '{0,0}'
);
   

更多细节参见 PostgreSQL 用户指南 中的 CREATE AGGREGATE。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。