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

  • name

    • 要创建的聚合函数的名称(可选的模式限定)。
  • argmode

    • 参数的模式:INVARIADIC。 (聚合函数不支持OUT参数.)如果省略,则默认值为IN。只有最后一个参数可以标记为VARIADIC
  • argname

    • 参数的名称。当前这仅用于文档目的。如果省略,则参数没有名称。
  • arg_data_type

    • 此聚合函数在其上操作的 Importing 数据类型。要创建零参数聚合函数,请写*代替参数规范列表。 (此类聚合的示例是count(*).)
  • base_type

    • CREATE AGGREGATE的旧语法中,Importing 数据类型由basetype参数指定,而不是写在聚合名称旁边。请注意,此语法仅允许一个 Importing 参数。要使用此语法定义零参数聚合函数,请将basetype指定为"ANY"(而不是*)。不能使用旧语法定义有序集合。
  • sfunc

    • 每个 Importing 行要调用的状态转换函数的名称。对于普通的N *参数聚合函数,sfunc 必须带有N * 1 个参数,第一个是 state_data_type 类型,其余匹配声明的聚合 Importing 数据类型。该函数必须返回 state_data_type *类型的值。该函数获取当前状态值和当前 Importing 数据值,然后返回下一个状态值。

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

  • state_data_type

    • 聚合状态值的数据类型。
  • state_data_size

    • 聚合状态值的近似平均大小(以字节为单位)。如果省略此参数或将其设置为零,则基于* state_data_type *使用默认估计。计划者使用此值来估计分组聚合查询所需的内存。仅当估计哈希表适合work_mem时,计划者才会考虑对此类查询使用哈希聚合;因此,此参数的较大值不鼓励使用哈希聚合。
  • ffunc

    • 在遍历所有 Importing 行之后,用来计算聚合结果的最终函数的名称。对于普通聚合,此函数必须采用* state_data_type 类型的单个参数。聚合的返回数据类型定义为该函数的返回类型。如果未指定 ffunc ,则将结束状态值用作聚合的结果,返回类型为 state_data_type *。

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

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

  • combinefunc

    • 可以可选地指定* combinefunc *函数,以允许聚合函数支持部分聚合。如果提供,则combinefunc 必须组合两个 state_data_type *值,每个值都包含在 Importing 值的某些子集上的聚合结果,以产生一个新的_state_data_type ,该值表示在两组 Importing 上进行聚合的结果。可以将此函数视为 sfunc *,在其中,它不作用于单个 Importing 行并将其添加到运行聚合状态,而是将另一个聚合状态添加到运行状态。
  • combinefunc 必须声明为接受 state_data_type 的两个参数并返回 state_data_type *的值。可选地,该功能可以是“严格的”。在这种情况下,当任何一个 Importing 状态为 null 时,将不会调用该函数;其他状态将被视为正确结果。

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

  • serialfunc

      • state_data_type internal的聚合函数只有具有 serialfunc 函数,该函数才能参与并行聚合,该函数必须将聚合状态序列化为bytea值才能传输到另一个进程。此函数必须采用internal类型的单个参数,并返回bytea类型。还需要相应的 deserialfunc *。
  • deserialfunc

    • 将先前序列化的聚合状态反序列化为* state_data_type *。此函数必须采用byteainternal类型的两个参数,并产生internal类型的结果。 (注意:第二个internal参数未使用,但出于类型安全的原因是必需的.)
  • initial_condition

    • 状态值的初始设置。这必须是数据类型* state_data_type *可接受的形式的字符串常量。如果未指定,则状态值开始为 null。
  • msfunc

    • 在移动聚合模式下为每个 Importing 行调用的前向状态转换函数的名称。这与常规转换函数完全相同,除了它的第一个参数和结果的类型为* mstate_data_type 之外,它可能与 state_data_type *不同。
  • minvfunc

    • 在移动聚合模式下使用的逆状态转换函数的名称。该函数的参数和结果类型与* msfunc *相同,但用于从当前聚合状态中删除一个值,而不是向其添加值。逆转换函数必须具有与前向状态转换函数相同的严格性属性。
  • mstate_data_type

    • 使用移动聚合模式时,聚合状态值的数据类型。
  • mstate_data_size

    • 使用移动聚合模式时,聚合状态值的近似平均大小(以字节为单位)。这与* state_data_size *相同。
  • mffunc

    • 使用移动聚合模式时,在遍历所有 Importing 行之后,用于计算聚合结果的最终函数的名称。它的作用与* ffunc 相同,不同之处在于其第一个参数的类型为 mstate_data_type *,并且通过写入MFINALFUNC_EXTRA指定了额外的伪参数。 * mffunc mstate_data_type *确定的聚合结果类型必须与聚合的常规实现所确定的结果类型匹配。
  • minitial_condition

    • 使用移动聚合模式时,状态值的初始设置。这与* initial_condition *相同。
  • sort_operator

    • 类似于MINMAX的聚合的关联排序运算符。这只是一个运算符名称(可能是模式限定的)。假定运算符具有与聚合相同的 Importing 数据类型(必须是单参数常规聚合)。
  • PARALLEL

    • PARALLEL SAFEPARALLEL RESTRICTEDPARALLEL UNSAFE的含义与CREATE FUNCTION相同。如果聚合标记为PARALLEL UNSAFE(这是默认设置!)或PARALLEL RESTRICTED,则不会考虑进行并行化。请注意,计划人员不咨询骨料支持功能的 Parallel 安全标记,而只咨询骨料本身的标记。
  • HYPOTHETICAL

    • 仅对于有序集合聚合,此标志指定将根据假设集合聚合的要求来处理聚合参数:也就是说,最后几个直接参数必须与聚合(WITHIN GROUP)参数的数据类型匹配。 HYPOTHETICAL标志对运行时行为没有影响,仅对数据类型的解析时解析和聚合参数的排序规则没有影响。

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