我正在尝试定义一个 PostgreSQL 聚合函数,该函数能够识别帧子句中被要求但缺失的行。具体来说,考虑一个聚合函数 framer
,它的作用是返回一个由通过它聚合的值组成的数组,其中框架中任何缺失的值都将返回为 null
。
select
n,
v,
framer(v) over (order by v rows between 2 preceding and 2 following) arr
from (values (1, 3200), (2, 2400), (3, 1600), (4, 2900), (5, 8200)) as v (n, v)
order by v
应该返回
"n" "v" "arr"
3 1600 {null,null,1600,2400,2900}
2 2400 {null,1600,2400,2900,3200}
4 2900 {1600,2400,2900,3200,8200}
1 3200 {2400,2900,3200,8200,null}
5 8200 {2900,3200,8200,null,null}
基本上,我想获取每个值周围的一定范围内的数值,并且知道左侧或右侧(或两侧)是否缺失对我非常重要。看起来很简单。我预期应该可以使用类似以下的方法:
create aggregate framer(anyelement) (
sfunc = array_append,
stype = anyarray,
initcond = '{}'
);
但是它返回的结果是:
"n" "v" "arr"
3 1600 {1600,2400,2900}
2 2400 {1600,2400,2900,3200}
4 2900 {1600,2400,2900,3200,8200}
1 3200 {2400,2900,3200,8200}
5 8200 {2900,3200,8200}
当两个值缺失时,实际上只调用了三次sfunc
。
我一直没有想到任何非荒谬的方式来捕获这些缺失的行。似乎应该有一个简单的解决方案,比如在聚合运行之前在数据中加入/添加一些哨兵空值,或者可能以某种方式将索引(和帧值)以及实际值传递给函数...
我希望将其实现为聚合,因为对于我想要做的事情,它提供了最好的用户体验。有更好的方法吗?
顺便说一下,我使用的是postgres 9.6。
size_
大于输入量时它就无法工作。考虑使用select n, v, framer(v, 3) over (order by v rows between 1 preceding and 1 following) arr from (values (1, 32), (2, 24)) as v (n, v) order by v;
应该返回{null, 24, 32}, {24, 32, null}
,但实际上返回的是{null, 24, 32}, {null, 24, 32}
。Postgres 调用framer_msfunc
两次来构建第一个结果,然后再也没有调用过,重复使用了第一个结果。因为 Postgres 愿意缓存结果,所以我想知道是否还有其他特殊情况会导致它出错。 - Chucky Ellison