CREATE AGGREGATE

CREATE AGGREGATE —定义一个新的聚合函数

Synopsis

CREATE AGGREGATE name ( [ argmode ] [ argname ] arg_data_type [ , ... ] ) (
    SFUNC = sfunc,
    STYPE = state_data_type
    [ , SSPACE = state_data_size ]
    [ , FINALFUNC = ffunc ]
    [ , FINALFUNC_EXTRA ]
    [ , COMBINEFUNC = combinefunc ]
    [ , SERIALFUNC = serialfunc ]
    [ , DESERIALFUNC = deserialfunc ]
    [ , INITCOND = initial_condition ]
    [ , MSFUNC = msfunc ]
    [ , MINVFUNC = minvfunc ]
    [ , MSTYPE = mstate_data_type ]
    [ , MSSPACE = mstate_data_size ]
    [ , MFINALFUNC = mffunc ]
    [ , MFINALFUNC_EXTRA ]
    [ , MINITCOND = minitial_condition ]
    [ , SORTOP = sort_operator ]
    [ , PARALLEL = { SAFE | RESTRICTED | UNSAFE } ]
)

CREATE AGGREGATE name ( [ [ argmode ] [ argname ] arg_data_type [ , ... ] ]
                        ORDER BY [ argmode ] [ argname ] arg_data_type [ , ... ] ) (
    SFUNC = sfunc,
    STYPE = state_data_type
    [ , SSPACE = state_data_size ]
    [ , FINALFUNC = ffunc ]
    [ , FINALFUNC_EXTRA ]
    [ , INITCOND = initial_condition ]
    [ , PARALLEL = { SAFE | RESTRICTED | UNSAFE } ]
    [ , HYPOTHETICAL ]
)

or the old syntax

CREATE AGGREGATE name (
    BASETYPE = base_type,
    SFUNC = sfunc,
    STYPE = state_data_type
    [ , SSPACE = state_data_size ]
    [ , FINALFUNC = ffunc ]
    [ , FINALFUNC_EXTRA ]
    [ , COMBINEFUNC = combinefunc ]
    [ , SERIALFUNC = serialfunc ]
    [ , DESERIALFUNC = deserialfunc ]
    [ , INITCOND = initial_condition ]
    [ , MSFUNC = msfunc ]
    [ , MINVFUNC = minvfunc ]
    [ , MSTYPE = mstate_data_type ]
    [ , MSSPACE = mstate_data_size ]
    [ , MFINALFUNC = mffunc ]
    [ , MFINALFUNC_EXTRA ]
    [ , MINITCOND = minitial_condition ]
    [ , SORTOP = sort_operator ]
)

Description

CREATE AGGREGATE定义了一个新的聚合函数。发行版中包含一些基本的和常用的聚合函数;它们记录在Section 9.20中。如果定义新类型或需要尚未提供的聚合函数,则CREATE AGGREGATE可用于提供所需的功能。

如果指定了架构名称(例如CREATE AGGREGATE myschema.myagg ...),则将在指定的架构中创建聚合函数。否则,它将在当前架构中创建。

聚合函数通过其名称和 Importing 数据类型进行标识。如果同一聚合中的两个聚合操作不同的 Importing 类型,则它们可以具有相同的名称。集合的名称和 Importing 数据类型还必须与同一模式中每个普通函数的名称和 Importing 数据类型不同。此行为与重载普通函数名相同(请参见CREATE FUNCTION)。

一个简单的聚合函数由一个或两个普通函数组成:状态转换函数* sfunc 和可选的最终计算函数 ffunc *。它们的用法如下:

sfunc( internal-state, next-data-values ) ---> next-internal-state
ffunc( internal-state ) ---> aggregate-value

PostgreSQL 创建一个数据类型* stype *的临时变量来保存聚合的当前内部状态。在每个 Importing 行,将计算一个或多个汇总参数值,并使用当前状态值和新的参数值调用状态转换函数,以计算新的内部状态值。在处理完所有行之后,将一次调用 final 函数以计算聚合的返回值。如果没有最终功能,则按原样返回最终状态值。

聚合函数可以提供初始条件,即内部状态值的初始值。它被指定为类型text并将其存储在数据库中,但是它必须是状态值数据类型的常量的有效外部表示形式。如果未提供,则状态值开始为 null。

如果状态转换函数被声明为“严格”,则不能使用空 Importing 来调用它。使用这种转换函数,聚合执行的行为如下。Importing 值为空的行将被忽略(不调用该函数,并且保留先前的状态值)。如果初始状态值为 null,则在具有全非 Importing 值的第一行,第一个自变量值将替换状态值,并在随后的具有全非 Importing 值的每一行调用转移函数。这对于实现max之类的聚合非常方便。请注意,仅当* state_data_type 与第一个 arg_data_type *相同时,此行为才可用。当这些类型不同时,必须提供一个非空的初始条件或使用一个非严格的转换函数。

如果状态转换函数不是严格的,则它将在每个 Importing 行无条件调用,并且必须自己处理空 Importing 和空状态值。这使聚合作者可以完全控制聚合对 null 值的处理。

如果最终函数被声明为“严格”,则当结束状态值为 null 时,将不会调用该函数;而是将自动返回空结果。 (当然,这只是严格函数的正常行为.)在任何情况下,最终函数都可以选择返回空值。例如,当avg的最终函数看到 Importing 行为零时,将返回 null。

有时将最终函数声明为不仅接受状态值,而且接受与聚合的 Importing 值相对应的额外参数是有用的。这样做的主要原因是,如果最终函数是多态的,并且状态值的数据类型不足以固定结果类型。这些额外的参数始终以 NULL 的形式传递(因此,使用FINALFUNC_EXTRA选项时,最终功能必须严格,但它们仍是有效参数)。最终函数可以例如使用get_fn_expr_argtype来标识当前调用中的实际参数类型。

Section 37.10.1中所述,聚合可以可选地支持* moving-aggregate 模式*。这需要指定MSFUNCMINVFUNCMSTYPE参数,以及可选的MSSPACEMFINALFUNCMFINALFUNC_EXTRAMINITCOND参数。除了MINVFUNC之外,这些参数的工作方式与不带M的相应简单聚合参数相同;它们定义了包含逆转换函数的聚合的单独实现。

参数列表中带有ORDER BY的语法会创建一种特殊的聚合类型,称为* ordered-setgregation ;或者,如果指定了HYPOTHETICAL,那么将创建一个假设集合聚合*。这些聚合以 Sequences 相关的方式对排序值的组进行操作,因此指定 Importing 排序 Sequences 是调用的必要部分。此外,它们可以具有* direct *参数,这些参数是每个聚合仅计算一次的参数,而不是每个 Importing 行评估一次的参数。假设集聚合是有序集聚合的子类,其中一些直接参数需要在数量和数据类型上与聚合参数列匹配。这允许将那些直接参数的值添加到集合 Importing 行的集合中,作为附加的“假设”行。

Section 37.10.4中所述,聚合可以可选地支持部分聚合。这需要指定COMBINEFUNC参数。如果* state_data_type *为internal,通常还应该提供SERIALFUNCDESERIALFUNC参数,以便可以进行并行聚合。请注意,还必须将聚合标记为PARALLEL SAFE才能启用并行聚合。

有时可以通过查找索引而不是扫描每个 Importing 行来优化行为类似于MINMAX的聚合。如果可以如此优化此聚合,请通过指定* sort 运算符*进行指示。基本要求是,集合必须在运算符引起的排序 Sequences 中产生第一个元素;换一种说法:

SELECT agg(col) FROM tab;

必须等于:

SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;

进一步的假设是,聚合将忽略空 Importing,并且当且仅当不存在非空 Importing 时,它才会提供空结果。通常,数据类型的<运算符是MIN的正确排序运算符,而>MAX的正确的排序运算符。注意,除非指定的运算符是 B 树索引运算符类的“小于”或“大于”策略成员,否则优化实际上不会生效。

为了能够创建聚合函数,您必须在参数类型,状态类型和返回类型上具有USAGE特权,并且在支持函数上必须具有EXECUTE特权。

Parameters

对于有序集(包括假设集)聚合,状态转换函数仅接收当前状态值和聚合参数,而不接收直接参数。否则是相同的。

对于有序集合(包括假设集合),最终函数不仅接收最终状态值,还接收所有直接参数的值。

如果指定了FINALFUNC_EXTRA,则除了最终状态值和任何直接参数外,最终函数还将接收与聚合的常规(聚合)参数相对应的额外 NULL 值。当定义多态聚合时,这主要用于允许正确解析聚合结果类型。

对于* state_data_type internal的聚合函数, combinefunc 不能严格。在这种情况下, combinefunc *必须确保正确处理空状态,并将返回的状态正确存储在聚合内存上下文中。

CREATE AGGREGATE的参数可以按任何 Sequences 写入,而不仅仅是上面说明的 Sequences。

Notes

在指定支持功能名称的参数中,可以根据需要编写模式名称,例如SFUNC = public.sum。但是,不要在那里写参数类型-支持函数的参数类型由其他参数确定。

如果聚合支持移动聚合模式,则当将该聚合用作具有移动帧开始的窗口(即UNBOUNDED PRECEDING以外的帧开始模式)的窗口函数时,它将提高计算效率。从概念上讲,前向过渡函数在 Importing 值从底部进入窗口框架时将 Importing 值添加到聚合的状态,而逆向过渡函数在它们将帧留在顶部时再次将其删除。因此,当值被删除时,它们总是以添加的 Sequences 被删除。每当调用逆转换函数时,它将因此接收最早添加但尚未删除的参数值。逆转换函数可以假定在删除最旧的行后,至少有一行将保持当前状态。 (如果不是这种情况,则窗口函数机制只是开始新的聚合,而不是使用逆转换函数.)

移动聚合模式的前向过渡函数不允许返回 NULL 作为新状态值。如果逆向转换函数返回 NULL,则表示该逆向函数无法逆转此特定 Importing 的状态计算,因此将对当前帧起始位置从头开始重做汇总计算。此约定允许在一些不常见的情况下无法从运行状态值中撤消的情况下使用移动聚合模式。

如果没有提供移动聚合实现,则聚合仍可用于移动帧,但是只要帧开始移动,PostgreSQL 都会重新计算整个聚合。请注意,无论聚合是否支持移动聚合模式,PostgreSQL 都可以处理移动帧结束而无需重新计算。这是通过 continue 向聚合状态添加新值来完成的。假定最终功能不会损坏聚合的状态值,因此即使在已获得一组帧边界的聚合结果值之后,聚合也可以 continue 进行。

有序集合聚合的语法允许为最后一个直接参数和最后一个聚合(WITHIN GROUP)参数都指定VARIADIC。但是,当前的实现以两种方式限制VARIADIC的使用。首先,有序集合聚合只能使用VARIADIC "any",而不能使用其他可变参数数组类型。其次,如果最后一个直接参数是VARIADIC "any",那么只能有一个聚合参数,并且它也必须是VARIADIC "any"。 (在系统目录中使用的表示形式中,这两个参数合并为一个VARIADIC "any"项,因为pg_proc不能表示具有多个VARIADIC参数的函数.)如果集合是假设集集合,则与VARIADIC "any"参数是假设的;前面的任何参数都表示其他直接参数,这些参数不受约束以匹配聚合参数。

当前,有序集的聚合不需要支持移动聚合模式,因为它们不能用作窗口函数。

有序集聚合当前不支持部分(包括并行)聚合。同样,它将永远不会用于包含DISTINCTORDER BY子句的聚合调用,因为在部分聚合期间不支持这些语义。

Examples

See Section 37.10.

Compatibility

CREATE AGGREGATE是 PostgreSQL 语言扩展。 SQL 标准不提供用户定义的聚合函数。

See Also

ALTER AGGREGATE, DROP AGGREGATE

上一章 首页 下一章