SQL Server 2008中使用CASE语句实现两行数据相减的问题
解决分组内数值差值计算的问题
首先来看你的场景:你有如下表数据:
| Column1 | Column2 |
|---|---|
| abc | 100 |
| abc | 200 |
想要得到的结果是 abc 100(即200-100的差值),但你尝试的查询返回了null,我们先拆解下问题出在哪。
你的原查询问题分析
你写的这段查询:
Select column1, sum( case when rownum=1 then column2 end - case when rownum=2 then column2 end ) from table group by column1
有两个核心问题:
- 这里的
rownum是全局行号,不是分组内的行序号,无法精准定位每个column1分组里的第1、第2行; - 每一行的
case表达式只会命中一个条件:第一行计算的是100 - null(结果为null),第二行是null - 200(结果也为null),sum两个null自然得到null。
正确的解法
方法1:用分组聚合函数直接计算(最简单)
如果你的需求就是每个分组内最大的column2减去最小的column2,这个方法最直接高效:
SELECT column1, MAX(column2) - MIN(column2) AS difference FROM your_table GROUP BY column1;
对你的数据来说,MAX(200)-MIN(100)=100,正好得到你想要的结果。
方法2:用窗口函数定位指定行计算
如果需要明确指定是第二行减第一行(比如行的顺序有特殊业务要求),可以先给分组内的行标记序号,再计算:
WITH ranked_data AS ( SELECT column1, column2, ROW_NUMBER() OVER (PARTITION BY column1 ORDER BY column2) AS rn FROM your_table ) SELECT column1, (SELECT column2 FROM ranked_data WHERE rn=2 AND column1=rd.column1) - (SELECT column2 FROM ranked_data WHERE rn=1 AND column1=rd.column1) AS difference FROM ranked_data rd WHERE rn=1 GROUP BY column1;
方法3:用LEAD()窗口函数简化写法
更简洁的方式是用LEAD()函数直接获取分组内下一行的column2值,再计算差值:
WITH data_with_next AS ( SELECT column1, column2, LEAD(column2) OVER (PARTITION BY column1 ORDER BY column2) AS next_column2 FROM your_table ) SELECT column1, next_column2 - column2 AS difference FROM data_with_next WHERE next_column2 IS NOT NULL;
LEAD()会自动获取当前行的下一行数据,当存在下一行时(也就是分组里的第一行),计算next_column2 - column2就是200-100=100。
内容的提问来源于stack exchange,提问作者Siva
相关产品推荐
相关产品推荐

