postgres中的累积乘法

Ben*_*Ben 2 postgresql

我想在 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 内使用“滞后”组合的窗口化?

任何帮助或示例小提琴示例将不胜感激。

Cra*_*ger 5

任何聚合函数都可以用作窗口函数来获取正在运行的聚合。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)