Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PgSQL上的累积值和有界值之和_Sql_Database_Postgresql_Recursion_Sum - Fatal编程技术网

PgSQL上的累积值和有界值之和

PgSQL上的累积值和有界值之和,sql,database,postgresql,recursion,sum,Sql,Database,Postgresql,Recursion,Sum,我正在努力编写关于PgSQL的查询 我的表有值,我必须累加它的值,但结果必须有界(在这种情况下介于0和30之间) 以下是数据集和预期结果: +----+--------+------------------------------------+ | id | value | expected_cumulated_sum_with_limits | +----+--------+------------------------------------+ | 1 | 3 |

我正在努力编写关于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(但我不确定这是一个好方法)


感谢您的帮助

我对递归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;

演示:

您所说的必须在0和30之间有界是什么意思?如果该值非常大,并且会导致累计总和低于0或高于30,该怎么办?对于第
行id=5
,为什么
具有限制的预期累计总和的值为30而不是22?@OtoShavadze前一行的调整累计值为0,因此,45被添加到0中,而不是实际的累积量。我认为最简单的方法是使用游标。非常好,递归确实是一种很好的方法,谢谢@ukasz kamiński!
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;