我想在 Postgres 中进行累积乘法,但找不到任何对此的引用。
我的表有一个序列号和一个值字段。
| seq | value |
| 0 | 1 |
| 1 | 3 |
| 2 | 5 |
| 3 | 7 |
Run Code Online (Sandbox Code Playgroud)
我想生成返回一个新列,其中第一行的“值”和所有其他条目的“值”乘以前一行的结果
| seq | value | result |
| 0 | 1 | 1 |
| 1 | 3 | 3 |
| 2 | 5 | 15 |
| 3 | 7 | 105 |
Run Code Online (Sandbox Code Playgroud)
我想要创建的函数有点像运行总计,它让我回到 sum() 函数,而不是使用乘法运算符自己创建函数。
我还将在查询的未来版本中从简单的 val*(prev_result) 更新该函数,因此不想构建一个“函数”来执行此操作。
我是否需要考虑使用“公用表表达式”使用“递归”将表连接回自身?
这将是最有效的方法还是我应该在 CTE 内使用“滞后”组合的窗口化?
任何帮助或示例小提琴示例将不胜感激。
任何聚合函数都可以用作窗口函数来获取正在运行的聚合。PostgreSQL 允许您从 SQL 定义自定义聚合。
因此,一种方法是使用实现类型乘法运算符的基础函数来定义累积乘法聚合。例如对于 int8:
CREATE AGGREGATE cumulative_mul(int8) (SFUNC = int8mul, STYPE = int8);
Run Code Online (Sandbox Code Playgroud)
然后您可以在窗口函数表达式中使用它,例如
SELECT
seq,
"value",
cumulative_mul("value") OVER (ORDER BY seq)
FROM t;
Run Code Online (Sandbox Code Playgroud)
请参阅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)
Run Code Online (Sandbox Code Playgroud)
...而且它也应该相当快,特别是如果 上有索引(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)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3412 次 |
| 最近记录: |