计算 SQL 服务器中的递减累积和

Compute a Decreasing Cumulative Sum in SQL Server

我想要实现的是非负列的累计和,其中每行减 1,但结果也必须是非负的。

例如,对于以下 table,对按 "ID" 列排序的 "VALUE" 列求和:

| ID | VALUE    |
-----------------
|  1 |        0 |
|  2 |        0 |
|  3 |        2 |
|  4 |        0 |
|  5 |        0 |
|  6 |        3 |
|  7 |        0 |
|  8 |        2 |
|  9 |        0 |
| 10 |        0 |
| 11 |        0 |
| 12 |        0 |

我预计:

| ID | VALUE    | SUM   |
-------------------------
|  1 |        0 |     0 |
|  2 |        0 |     0 |
|  3 |        2 |     2 |
|  4 |        0 |     1 |
|  5 |        0 |     0 |
|  6 |        3 |     3 |
|  7 |        0 |     2 |
|  8 |        2 |     3 |
|  9 |        0 |     2 |
| 10 |        0 |     1 |
| 11 |        0 |     0 |
| 12 |        0 |     0 |

你的问题描述的不是很清楚。我最好的解释是你想从正数开始倒数,当你击中下一个时重新开始。

您可以使用非零值的累积和来定义组。然后对组使用累加和:

select t.*,
       (case when max(value) over (partition by grp) < row_number() over (partition by grp order by id) - 1
             then 0
             else (max(value) over (partition by grp) - 
                   (row_number() over (partition by grp order by id) - 1)
                  )
        end) as my_value
from (select t.*,
             sum(case when value <> 0 then 1 else 0 end) over (order by id) as grp
      from t
     ) t

Here 是一个 db<>fiddle.

编辑:

让我印象深刻的是,您可能想要保留所有 "positive" 值并倒数 - 记住它们是否不会下降到零。唉,在这种情况下,我认为最简单的方法是递归 CTE:

with tn as (
      select t.id, t.value, row_number() over (order by id) as seqnum
      from t
     ),
     cte as (
      select tn.id, tn.value, tn.seqnum, tn.value as s
      from tn
      where id = 1
      union all
      select tn.id, tn.value, tn.seqnum,
             (case when cte.s = 0
                   then tn.value
                   when tn.value = 0 and cte.s > 0
                   then cte.s - 1
                   --  when tn.value > 0 and cte.value > 0
                   else tn.value + cte.s - 1
              end)
      from cte join
           tn 
           on tn.seqnum = cte.seqnum + 1
     )
select *
from cte;

db<>fiddle 有两种解决方案。