PgSQL上的值的累积和有界和

时间:2018-08-16 07:56:04

标签: sql database postgresql recursion sum

我正在努力在PgSQL上编写查询。

我的表有值,我必须累加它的值,但是结果必须是有界的(在这种情况下,值为0到30之间)。

这是数据集和预期结果:

+----+--------+------------------------------------+
| id | value  | expected_cumulated_sum_with_limits |
+----+--------+------------------------------------+
|  1 |      3 |                                  3 |
|  2 |      4 |                                  7 |
|  3 |     -2 |                                  5 |
|  4 |    -28 |                                  0 |
|  5 |     45 |                                 30 |
|  6 |     -3 |                                 27 |
+----+--------+------------------------------------+

我用WINDOW尝试了一些查询(但是我只能做一个总和,没有0,30的限制)和一些递归CTE(但是我不确定这是个好方法)。

感谢您的帮助

1 个答案:

答案 0 :(得分:2)

我对递归CTE不太满意,因此可能有更好的方法,但这可行:

CREATE TABLE cum_bounded (id int4, value int4);
INSERT INTO cum_bounded VALUES (1,3), (2,4), (3,-2), (4,-28), (5,45), (6,-3);

如果ID没有空格,并且您要计算按ID排序的值:

WITH RECURSIVE cum AS (
  (SELECT c.id, c.value, c.value AS cum_value FROM cum_bounded AS c ORDER BY c.id LIMIT 1)
  UNION ALL
  SELECT c.id, c.value,
         CASE WHEN cum.cum_value + c.value < 0 THEN 0
              WHEN cum.cum_value + c.value > 30 THEN 30
              ELSE cum.cum_value + c.value END
  FROM cum_bounded AS c
  JOIN cum ON cum.id = c.id - 1
)
SELECT * FROM cum;

如果ID有空白,则检查下一个ID是什么(按ID排序)。也可以改为计算row_number()

WITH RECURSIVE cum AS (
  WITH cb AS (SELECT id, lead(id) OVER(ORDER BY c.id) AS next_id, c.value FROM cum_bounded AS c)
  (SELECT c.id, c.next_id, c.value, c.value AS cum_value FROM cb AS c ORDER BY 2 LIMIT 1)
  UNION ALL
  SELECT c.id, c.next_id, c.value,
         CASE WHEN cum.cum_value + c.value < 0 THEN 0
              WHEN cum.cum_value + c.value > 30 THEN 30
              ELSE cum.cum_value + c.value END
  FROM cb AS c
  JOIN cum ON cum.next_id = c.id
)
SELECT id, value, cum_value FROM cum;

演示:http://rextester.com/UCEDK41004