我使用的是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聚合函数的示例?
答案 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。