自定义Greenplum聚合功能与窗口

时间:2017-01-26 14:26:49

标签: sql aggregate-functions greenplum

我使用的是Greenplum DB,我想在窗口中计算中位数,例如:

SELECT avg(var1) OVER (PARTITION BY var2 ORDER BY datetime 
                       ROWS BETWEEN 10 PRECEDING AND CURRENT ROW) FROM tbl...

不幸的是,在Postgres中没有实现中位数,所以我使用这个例子创建了自己的聚合: https://wiki.postgresql.org/wiki/Aggregate_Median

问题在于,当我使用整列而不是在窗口中(使用OVER子句)返回错误时,这是​​有效的,并且#f; prefunc'应该定义。 Greenplum文档证实: http://gpdb.docs.pivotal.io/4380/ref_guide/sql_commands/CREATE_AGGREGATE.html

prefunc的文档和角色对我来说不是很清楚。您是否有任何定义支持Windows的自定义Postgres聚合函数的示例?

2 个答案:

答案 0 :(得分:1)

我不知道这是否适用于Greenplum。但是,在Postgres的现代版本中,您可以使用array_agg()作为窗口函数。因此,对于您的特殊问题,运行中位数为:

select (array_agg(var1) over (partition by var2 order by datetime
                              rows between 10 preceding and current row
                             )[6] as running_median

编辑:

另一种方法是使用子查询:

select t.*,
       (select t2.var1
        from t t2
        where t2.var2 = t.var2 and t2.datetime < t.datetime
        order by t2.datetime desc
        offset 5 limit 1
       ) running_median        
from t;

答案 1 :(得分:0)

要在GPDB中创建自定义聚合,您需要定义PREFUNC,它不是常规Postgres中的参数。

在正常的Postgres中,聚合需要一个起始状态(例如STYPE=numeric[])和一个告诉它如何将新项添加到当前状态(例如SFUNC=array_append)的函数。但是在像GPDB这样在分布式节点之间移动数据的分布式系统中,从两个地方(即两个数组)接收状态的节点如何组合两种状态呢?这就是PREFUNC的作用。然后,最后可以在单个组合状态上调用FINALFUNC并返回。

在计算中位数的示例中,您需要做的就是将PREFUNC=array_cat,添加到从median example code获取的聚合定义中。 array_cat接受两个数组并将它们作为单个组合数组返回。我已经尝试过它,它对我来说既可以作为聚合也可以作为窗口。

(请注意,使用numeric[]的版本有效,但由于某种原因不是anyarray。看来是因为创建窗口/聚合函数不重要的原因。)< / em>的

有关聚合的更多信息,请参阅Lukasz所提及的GPDB docs