带窗口的自定义Greenplum聚合函数

Posted

技术标签:

【中文标题】带窗口的自定义Greenplum聚合函数【英文标题】:Custom Greenplum aggregate function with window 【发布时间】:2017-01-26 14:26:48 【问题描述】:

我正在使用 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 子句)返回错误时,这有效,应该定义“prefunc”。 Greenplum 文档证实: http://gpdb.docs.pivotal.io/4380/ref_guide/sql_commands/CREATE_AGGREGATE.html

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

【问题讨论】:

【参考方案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;

【讨论】:

Greenplum 基于 PostgreSQL 8.2.15 。我认为 array_agg() 在这个版本中不可用。 array_agg() 在 GPDB 中。 array_agg() 有效,但 group by 不带窗口,我仍然收到ERROR: aggregate functions with no prelimfn or invprelimfn are not yet supported as window functions @Lukasz 。 . .它确实适用于更新版本的 Postgres(是的,我在发布之前测试了这个答案)。【参考方案2】:

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

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

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

(请注意,采用numeric[] 的版本可以工作,但由于某种原因不是anyarray 的版本。似乎原因对于创建窗口/聚合函数并不重要。)

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

【讨论】:

太好了,很高兴@Lukasz 有帮助。如果您觉得答案值得,我会非常感谢您的支持和marking it as accepted。

以上是关于带窗口的自定义Greenplum聚合函数的主要内容,如果未能解决你的问题,请参考以下文章

Greenplum优化--SQL调优篇

Greenplum优化--SQL调优篇

窗口聚合函数与分组聚合函数的异同

极简spark教程spark聚合函数

C#怎么调用sqlserver的自定义函数

MySQL窗口函数_聚合函数