On this page
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 ]
[ , FINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE } ]
[ , 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 ]
[ , MFINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE } ]
[ , 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 ]
[ , FINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE } ]
[ , 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 ]
[ , FINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE } ]
[ , 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 ]
[ , MFINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE } ]
[ , 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 38.11.1中所述,聚合可以可选地支持* moving-aggregate 模式*。这需要指定MSFUNC
,MINVFUNC
和MSTYPE
参数,以及可选的MSSPACE
,MFINALFUNC
,MFINALFUNC_EXTRA
,MFINALFUNC_MODIFY
和MINITCOND
参数。除了MINVFUNC
以外,这些参数的工作方式与不带M
的相应简单汇总参数相同;它们定义了包含逆转换函数的聚合的单独实现。
参数列表中带有ORDER BY
的语法会创建一种特殊的聚合类型,称为* ordered-setgregation ;或者,如果指定了HYPOTHETICAL
,那么将创建一个假设集合聚合*。这些聚合以 Sequences 相关的方式对排序值的组进行操作,因此指定 Importing 排序 Sequences 是调用的必要部分。此外,它们可以具有* direct *参数,这些参数是每个聚合仅计算一次的参数,而不是每个 Importing 行评估一次的参数。假设集聚合是有序集聚合的子类,其中一些直接参数需要在数量和数据类型上与聚合参数列匹配。这允许将那些直接参数的值添加到集合 Importing 行的集合中,作为附加的“假设”行。
如Section 38.11.4中所述,聚合可以可选地支持部分聚合。这需要指定COMBINEFUNC
参数。如果* state_data_type
*为internal
,通常还应该提供SERIALFUNC
和DESERIALFUNC
参数,以便可以进行并行聚合。请注意,还必须将聚合标记为PARALLEL SAFE
才能启用并行聚合。
有时可以通过查找索引而不是扫描每个 Importing 行来优化行为类似于MIN
或MAX
的聚合。如果可以如此优化此聚合,请通过指定* 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
- 参数的模式:
IN
或VARIADIC
。 (聚合函数不支持OUT
参数.)如果省略,则默认值为IN
。只有最后一个参数可以标记为VARIADIC
。
- 参数的模式:
argname
- 参数的名称。当前这仅用于文档目的。如果省略,则参数没有名称。
arg_data_type
- 此聚合函数在其上操作的 Importing 数据类型。要创建零参数聚合函数,请写
*
代替参数规范列表。 (此类聚合的示例是count(*)
.)
- 此聚合函数在其上操作的 Importing 数据类型。要创建零参数聚合函数,请写
base_type
- 在
CREATE AGGREGATE
的旧语法中,Importing 数据类型由basetype
参数指定,而不是写在聚合名称旁边。请注意,此语法仅允许一个 Importing 参数。要使用此语法定义零参数聚合函数,请将basetype
指定为"ANY"
(而不是*
)。不能使用旧语法定义有序集合。
- 在
sfunc
- 每个 Importing 行要调用的状态转换函数的名称。对于普通的
N
参数聚合函数,sfunc
必须采用N
* 1 个参数,第一个为state_data_type
类型,其余与声明的聚合 Importing 数据类型匹配。该函数必须返回state_data_type
*类型的值。该函数获取当前状态值和当前 Importing 数据值,然后返回下一个状态值。
- 每个 Importing 行要调用的状态转换函数的名称。对于普通的
对于有序集(包括假设集)聚合,状态转换函数仅接收当前状态值和聚合参数,而不接收直接参数。否则是相同的。
state_data_type
- 聚合状态值的数据类型。
state_data_size
- 聚合状态值的近似平均大小(以字节为单位)。如果省略此参数或将其设置为零,则基于*
state_data_type
*使用默认估计。计划者使用此值来估计分组聚合查询所需的内存。仅当估计哈希表适合work_mem时,计划者才会考虑对此类查询使用哈希聚合;因此,此参数的较大值不鼓励使用哈希聚合。
- 聚合状态值的近似平均大小(以字节为单位)。如果省略此参数或将其设置为零,则基于*
ffunc
- 在遍历所有 Importing 行之后,用来计算聚合结果的最终函数的名称。对于普通聚合,此函数必须采用*
state_data_type
类型的单个参数。聚合的返回数据类型定义为该函数的返回类型。如果未指定ffunc
,则将结束状态值用作聚合的结果,返回类型为state_data_type
*。
- 在遍历所有 Importing 行之后,用来计算聚合结果的最终函数的名称。对于普通聚合,此函数必须采用*
对于有序集合(包括假设集合),最终函数不仅接收最终状态值,还接收所有直接参数的值。
如果指定了FINALFUNC_EXTRA
,则除了最终状态值和任何直接参数外,最终函数还将接收与聚合的常规(聚合)参数相对应的额外 NULL 值。当定义多态聚合时,这主要用于允许正确解析聚合结果类型。
FINALFUNC_MODIFY
= {READ_ONLY
|SHAREABLE
|READ_WRITE
}- 此选项指定最终函数是否为不修改其参数的纯函数。
READ_ONLY
表示不;其他两个值表示它可能会更改过渡状态值。有关更多详细信息,请参见下面的Notes。默认值为READ_ONLY
,但有序集合除外,默认值为READ_WRITE
。
- 此选项指定最终函数是否为不修改其参数的纯函数。
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
*。此函数必须采用bytea
和internal
类型的两个参数,并产生internal
类型的结果。 (注意:第二个internal
参数未使用,但出于类型安全的原因是必需的.)
- 将先前序列化的聚合状态反序列化为*
initial_condition
- 状态值的初始设置。这必须是数据类型*
state_data_type
*可接受的形式的字符串常量。如果未指定,则状态值开始为 null。
- 状态值的初始设置。这必须是数据类型*
msfunc
- 在移动聚合模式下为每个 Importing 行调用的前向状态转换函数的名称。这与常规转换函数完全相同,除了它的第一个参数和结果的类型为*
mstate_data_type
之外,它可能与state_data_type
*不同。
- 在移动聚合模式下为每个 Importing 行调用的前向状态转换函数的名称。这与常规转换函数完全相同,除了它的第一个参数和结果的类型为*
minvfunc
- 在移动聚合模式下使用的逆状态转换函数的名称。该函数的参数和结果类型与*
msfunc
*相同,但用于从当前聚合状态中删除一个值,而不是向其添加值。逆转换函数必须具有与前向状态转换函数相同的严格性属性。
- 在移动聚合模式下使用的逆状态转换函数的名称。该函数的参数和结果类型与*
mstate_data_type
- 使用移动聚合模式时,聚合状态值的数据类型。
mstate_data_size
- 使用移动聚合模式时,聚合状态值的近似平均大小(以字节为单位)。这与*
state_data_size
*相同。
- 使用移动聚合模式时,聚合状态值的近似平均大小(以字节为单位)。这与*
mffunc
- 使用移动聚合模式时,在遍历所有 Importing 行之后,用于计算聚合结果的最终函数的名称。它的作用与*
ffunc
相同,不同之处在于其第一个参数的类型为mstate_data_type
*,并且通过写入MFINALFUNC_EXTRA
指定了额外的伪参数。 *mffunc
或mstate_data_type
*确定的聚合结果类型必须与聚合的常规实现所确定的结果类型匹配。
- 使用移动聚合模式时,在遍历所有 Importing 行之后,用于计算聚合结果的最终函数的名称。它的作用与*
MFINALFUNC_MODIFY
= {READ_ONLY
|SHAREABLE
|READ_WRITE
}- 此选项类似于
FINALFUNC_MODIFY
,但是它描述了移动聚集最终函数的行为。
- 此选项类似于
minitial_condition
- 使用移动聚合模式时,状态值的初始设置。这与*
initial_condition
*相同。
- 使用移动聚合模式时,状态值的初始设置。这与*
sort_operator
- 类似于
MIN
或MAX
的聚合的关联排序运算符。这只是一个运算符名称(可能是模式限定的)。假定运算符具有与聚合相同的 Importing 数据类型(必须是单参数常规聚合)。
- 类似于
PARALLEL =
{SAFE
|RESTRICTED
|UNSAFE
}PARALLEL SAFE
,PARALLEL RESTRICTED
和PARALLEL UNSAFE
的含义与CREATE FUNCTION相同。如果聚合标记为PARALLEL UNSAFE
(这是默认设置!)或PARALLEL RESTRICTED
,则不会考虑进行并行化。请注意,计划人员不咨询骨料支持功能的 Parallel 安全标记,而只咨询骨料本身的标记。
HYPOTHETICAL
- 仅对于有序集合聚合,此标志指定将根据假设集合聚合的要求来处理聚合参数:也就是说,最后几个直接参数必须与聚合(
WITHIN GROUP
)参数的数据类型匹配。HYPOTHETICAL
标志对运行时行为没有影响,仅对数据类型的解析时解析和聚合参数的排序规则没有影响。
- 仅对于有序集合聚合,此标志指定将根据假设集合聚合的要求来处理聚合参数:也就是说,最后几个直接参数必须与聚合(
CREATE AGGREGATE
的参数可以按任何 Sequences 写入,而不仅仅是上面说明的 Sequences。
Notes
在指定支持功能名称的参数中,可以根据需要编写模式名称,例如SFUNC = public.sum
。但是,不要在那里写参数类型-支持函数的参数类型由其他参数确定。
通常,PostgreSQL 函数应该是不修改其 Importing 值的真实函数。但是,当在聚合上下文中使用时,允许聚合过渡函数作弊并在适当位置修改其过渡状态参数。与每次重新制作过渡状态副本相比,这可以提供显着的性能优势。
同样,尽管通常期望汇总的最终函数不修改其 Importing 值,但有时避免修改过渡状态参数是不切实际的。必须使用FINALFUNC_MODIFY
参数声明这种行为。 READ_WRITE
值指示最终函数以未指定的方式修改过渡状态。此值防止将聚合用作窗口函数,并且还防止合并共享相同 Importing 值和转换函数的聚合调用的转换状态。 SHAREABLE
值指示过渡功能不能在最终功能之后应用,但是可以对结束的过渡状态值执行多个最终功能调用。该值防止将聚合用作窗口函数,但允许合并过渡状态。 (也就是说,此处关注的优化不是重复应用相同的最终函数,而是将不同的最终函数应用于相同的结束过渡状态值.只要没有将最终函数标记为READ_WRITE
,就可以这样做.)
如果聚合支持移动聚合模式,则当将该聚合用作具有移动帧开始的窗口(即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"
参数是假设的;前面的任何参数都表示其他直接参数,这些参数不受约束以匹配聚合参数。
当前,有序集的聚合不需要支持移动聚合模式,因为它们不能用作窗口函数。
有序集聚合当前不支持部分(包括并行)聚合。同样,它将永远不会用于包含DISTINCT
或ORDER BY
子句的聚合调用,因为在部分聚合期间不支持这些语义。
Examples
See Section 38.11.
Compatibility
CREATE AGGREGATE
是 PostgreSQL 语言扩展。 SQL 标准不提供用户定义的聚合函数。