postgres累积乘法

时间:2015-08-12 12:59:58

标签: postgresql

我想在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中使用窗口?

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

2 个答案:

答案 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;

Sample SQL Fiddle