如何在SQL Server的CASE WHEN语句中递增局部变量?
在SQL Server中基于错误场景生成分组ID的正确实现
原代码的问题
你之前的写法存在两个核心问题:
- 语法错误:SQL Server不允许在
SELECT语句中同时给局部变量赋值并将其作为结果列返回,这会直接触发语法报错。 - 逻辑不可靠:即使绕过语法问题,依赖局部变量逐行递增的方式也无法保证结果正确——SQL Server不承诺
SELECT语句的执行顺序和输出顺序一致,变量的累加结果可能完全不符合预期。
正确解决方案:用窗口函数实现分组ID
要实现按指定错误场景递增分组ID的需求,推荐使用SUM() OVER()窗口函数来累计分组触发条件,这是SQL Server中生成这类分组的标准、可靠方法。
完整代码示例
WITH CTE_Movements AS ( SELECT a.CPUT AS Tim, a.USNA AS wayq, a.WE AS Pl, a.MA AS Mau, b.MAK AS Material_Desc, a.BW AS Movement_type, c.BTE AS Movement_Type_Text, LAG(a.BW) OVER (ORDER BY a.MB, a.ZE) AS Prev_Movement_type, -- 标记当前行是否需要开启新分组 CASE WHEN (a.BW IN ('13', '16') AND LAG(a.BW) OVER (ORDER BY a.MB, a.ZE) IN ('14', '15')) THEN 1 ELSE 0 END AS Is_New_Group, a.MB, a.ZE FROM Database_Table3 a LEFT JOIN Database_Table4 b ON a.MA = b.MA LEFT JOIN Database_Table5 c ON a.BW = c.BW WHERE a.BW IN ('13', '14', '15', '16') ) SELECT Tim, wayq, Pl, Mau, Material_Desc, Movement_type, Movement_Type_Text, Prev_Movement_type, -- 累计新分组标记,生成连续的GroupID SUM(Is_New_Group) OVER (ORDER BY MB, ZE ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + 1 AS GroupID FROM CTE_Movements ORDER BY MB, ZE;
代码说明
- CTE预处理:先通过公共表表达式(CTE)筛选数据,计算每行的
Prev_Movement_type,并标记Is_New_Group——当满足你定义的错误场景(当前移动类型是13/16且上一行是14/15)时,标记为1,否则为0。 - 生成GroupID:在主查询中,用
SUM(Is_New_Group) OVER(...)累计从第一行到当前行的所有新分组标记值,再加上初始值1,就能得到连续递增的分组ID。每遇到一个错误场景,GroupID自动加1。
扩展说明
如果需要按MB字段进行独立分组(即每个MB内部单独生成GroupID),只需修改窗口函数的OVER子句,添加PARTITION BY MB:
SUM(Is_New_Group) OVER (PARTITION BY MB ORDER BY ZE ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + 1 AS GroupID
内容的提问来源于stack exchange,提问作者name mon
相关产品推荐
相关产品推荐

