我想在Postgres中进行累积乘法,但找不到任何对此的引用。
我的表有一个序列号和一个值字段。
| seq | value |
| 0 | 1 |
| 1 | 3 |
| 2 | 5 |
| 3 | 7 |
我希望生成一个新列,它返回第一行的'value','value'乘以所有其他条目的前一行结果
| seq | value | result |
| 0 | 1 | 1 |
| 1 | 3 | 3 |
| 2 | 5 | 15 |
| 3 | 7 | 105 |
我想要创建的函数有点像运行总计,它指向sum()函数,而不是使用乘法运算符自己创建函数。
我还将在查询的未来版本中从简单的val *(prev_result)更新函数,因此不想构建一个“函数”来执行此操作。
我是否需要使用'recursive with'使用'公用表表达式'来查看将表连接回自身?
这是最有效的方法还是应该使用'滞后'组合在CTE中使用窗口?
任何帮助或示例小提琴示例都将不胜感激。
答案 0 :(得分:3)
任何聚合函数都可以用作窗口函数来获取正在运行的聚合。 PostgreSQL允许您从SQL定义自定义聚合。
因此,一种方法是使用实现类型的乘法运算符的基础函数来定义累积乘法聚合。例如对于int8:
CREATE AGGREGATE cumulative_mul(int8) (SFUNC = int8mul, STYPE = int8);
然后,您可以在窗口函数表达式中使用它,例如
SELECT
seq,
"value",
cumulative_mul("value") OVER (ORDER BY seq)
FROM t;
请参阅SQLFiddle。
结果:
test=> SELECT
seq,
"value",
cumulative_mul("value") OVER (ORDER BY seq)
FROM t;
seq | value | cumulative_mul
-----+-------+----------------
0 | 1 | 1
1 | 3 | 3
2 | 5 | 15
3 | 7 | 105
(4 rows)
...它应该也很快,特别是如果(seq, value)
上有索引,允许PostgreSQL进行仅索引扫描:
test=> explain SELECT
seq,
"value",
cumulative_mul("value") OVER (ORDER BY seq)
FROM t;
QUERY PLAN
---------------------------------------------------------------------------
WindowAgg (cost=0.13..8.26 rows=4 width=8)
-> Index Only Scan using seqval on t (cost=0.13..8.19 rows=4 width=8)
(2 rows)
答案 1 :(得分:1)
使用递归公用表表达式应该可行,但对于较大的数据集可能无法很好地扩展:
with recursive c(seq, value) as (
select seq, value from t
union all
select t.seq, c.value * t.value
from t join c on t.seq = c.seq + 1
)
select seq, max(value) as value
from c
group by seq
order by seq;