--sfunc( internal-state, next-data-values ) ---> next-internal-state
CREATE OR REPLACE FUNCTION sum_transfn (state int4 , n int4)
RETURNS int4
AS $$
DECLARE
new_state int4;
BEGIN
RAISE NOTICE 'sum_transfn called with state: %, n=%' , state , n;
IF state IS NULL THEN
RAISE NOTICE 'compute where state is null';
IF n IS NOT NULL THEN
new_state := n;
RAISE NOTICE 'new_state: %' , new_state;
RETURN new_state;
END IF;
RETURN NULL;
ELSIF n IS NOT NULL THEN
RAISE NOTICE 'compute where n = %' , n;
RAISE NOTICE 'state = %' , state;
state := state + n;
RAISE NOTICE 'now state = %' , state;
RETURN state;
END IF;
RETURN NULL;
END
$$
LANGUAGE plpgsql;
创建聚合:
create aggregate my_sum(int4)
(
stype = int4,
sfunc = sum_transfn
);
调用聚合:
select my_sum(one)from (values (1),(2),(3),(4)) t(one);
返回
NOTICE: sum_transfn called with state: <NULL>, n=1
NOTICE: compute where state is null
NOTICE: new_state: 1
NOTICE: sum_transfn called with state: 1, n=2
NOTICE: compute where n = 2
NOTICE: state = 1
NOTICE: now state = 3
NOTICE: sum_transfn called with state: 3, n=3
NOTICE: compute where n = 3
NOTICE: state = 3
NOTICE: now state = 6
NOTICE: sum_transfn called with state: 6, n=4
NOTICE: compute where n = 4
NOTICE: state = 6
NOTICE: now state = 10
+--------+
| my_sum |
+--------+
| 10 |
+--------+
在高层次上,我通过使用加薪通知来获得它。但总的来说,我没有得到很多部分。喜欢:
- 有两个
return null;
。firstreturn null
表示如果 state 为 null 且 n 为 null 则返回 null?第二个 null 表示 state 不为 null 且 n 为 null 然后返回 null? - my_sum(one) 只有一个输入参数,所以明确分配状态为空,n = 一?我有点明白。由于手册提到:如果未提供,则状态值开始为空。
if state is null then .... return new_state;
所以聚合 sfunc 会隐式地将new_state分配给state,因为 state 是内部状态值?
如果我们逐步检查正在发生的事情,也许会变得更清楚。
聚合函数的状态被初始化为 NULL(因为没有
INITCOND
)。(虚拟)表开始被扫描,返回的第一行包含 1。
用and
SFUNC
调用,结果为 1。这个结果被分配给状态。n = 1
state = NULL
扫描该表以查找下一行,即 2。
用and
SFUNC
调用,得到 3,分配给状态。n = 2
state = 1
对接下来的两个表行重复步骤 4 和 5,之后状态为 10。
由于没有
FINALFUNC
,因此状态成为聚合函数的结果。这就是聚合函数的处理方式。聚合只有一个参数,因为状态是一个实现细节。