如何在SQL Server与Oracle中实现列当前值与前值的比较及计算
这需求很常见,用窗口函数就能轻松搞定!下面分别给你SQL Server和Oracle的实现方案,注意一定要明确行的排序规则——SQL里没有天然的“前一行”,必须靠排序字段(比如主键、时间戳这类能唯一确定行顺序的列)来定义顺序,不然结果会不可预期。
SQL Server 实现
我们用LAG()窗口函数来获取前一行的对应列值,再通过CASE语句判断条件后计算显示值:
SELECT T1.C1, T1.C2, CASE -- 对比当前行与前一行的C1、C2,且当前C3为指定值 WHEN T1.C1 = LAG(T1.C1) OVER (ORDER BY [你的排序字段]) AND T1.C2 = LAG(T1.C2) OVER (ORDER BY [你的排序字段]) AND T1.C3 = 'some value' -- 修正了原提问里的拼写错误 THEN LAG(T1.C3) OVER (ORDER BY [你的排序字段]) + 1 ELSE T1.C3 -- 不满足条件时保持原C3值 END AS C3 FROM T1;
补充说明
- 把
[你的排序字段]替换成实际用来排序的列(比如ID、CreateTime),确保行的顺序是你期望的。 - 如果需要在相同C1、C2的分组内对比前一行,可以把
ORDER BY改成PARTITION BY C1, C2 ORDER BY [你的排序字段],这样只会在同一个C1+C2组内查找前一行。
Oracle 实现
Oracle的LAG()函数用法和SQL Server几乎一致,实现代码如下:
SELECT T1.C1, T1.C2, CASE WHEN T1.C1 = LAG(T1.C1) OVER (ORDER BY 你的排序字段) AND T1.C2 = LAG(T1.C2) OVER (ORDER BY 你的排序字段) AND T1.C3 = 'some value' THEN LAG(T1.C3) OVER (ORDER BY 你的排序字段) + 1 ELSE T1.C3 END AS C3 FROM T1;
补充说明
- 同样要替换
你的排序字段为实际排序列,保证行顺序正确。 - 分组对比的场景同样可以用
PARTITION BY C1, C2 ORDER BY 你的排序字段来实现。
如果你的数据库版本非常老旧(比如SQL Server 2008及以前、Oracle 9i及以前),不支持LAG()函数,可以用自连接+子查询的方式实现,但窗口函数的写法更简洁高效,优先推荐。
内容的提问来源于stack exchange,提问作者Sowmya Dhandapani
相关产品推荐
相关产品推荐

