SQL Server中按连续状态分组计算Value累加和的技术问题
解决连续相同Status的Value累加求和问题
这是一个典型的连续分组(岛屿)求和问题——你需要把连续出现的相同Status看作独立分组,而非将所有同Status的记录合并,这也是直接用GROUP BY Status无法满足需求的原因。
问题分析
你之前的查询:
select Status, (select sum(value) from table t2 where t2.Status = t.Status and t2.SNO <= t.SNO ) as total from table t;
会累加所有当前行及之前的同Status记录,哪怕这些记录不连续(比如第6行的K会把第1-3行的K也加进去),所以无法得到"仅连续组累加"的结果。
解决方案:用窗口函数生成连续组标识
我们可以通过两个ROW_NUMBER()窗口函数的差值,为每个连续的Status组分配唯一的group_id——连续相同的Status会得到相同的group_id,非连续的重复Status则会得到不同的group_id。
步骤1:生成连续组标识
先执行以下查询,查看group_id的生成逻辑:
SELECT Id, Status, Value, -- 用全局行号减去按Status分区的行号,得到连续组ID ROW_NUMBER() OVER (ORDER BY Id) - ROW_NUMBER() OVER (PARTITION BY Status ORDER BY Id) AS group_id FROM your_table;
执行后结果如下:
| Id | Status | Value | group_id |
|---|---|---|---|
| 1 | K | 1 | 0 |
| 2 | K | 3 | 0 |
| 3 | K | 2 | 0 |
| 4 | B | 2 | 3 |
| 5 | B | 3 | 3 |
| 6 | K | 6 | 2 |
| 7 | J | 5 | 6 |
| 8 | J | 2 | 6 |
可以看到,连续的K(Id1-3)、B(Id4-5)、新的K(Id6)、J(Id7-8)分别被分到了不同的group_id组。
步骤2:按组求和
基于上面的子查询,我们按Status和group_id分组求和,再按组的最小Id排序(保证结果顺序和原数据中组的出现顺序一致):
SELECT Status, SUM(Value) AS Value FROM ( SELECT Id, Status, Value, ROW_NUMBER() OVER (ORDER BY Id) - ROW_NUMBER() OVER (PARTITION BY Status ORDER BY Id) AS group_id FROM your_table ) AS grouped GROUP BY Status, group_id ORDER BY MIN(Id);
最终结果
执行上述查询后,会得到你预期的结果:
| Status | Value |
|---|---|
| K | 6 |
| B | 5 |
| K | 6 |
| J | 7 |
内容的提问来源于stack exchange,提问作者CrazyCoder
相关产品推荐
相关产品推荐

