Oracle LAG函数无WHERE子句时的薪资计算异常问题
哈哈,这个问题我之前帮好几个同事排查过!核心问题其实很简单——你没给LAG()函数加上**分区(PARTITION BY)**子句~
问题根源
默认情况下,LAG()是在整个查询结果集的范围内取上一行数据:
- 当你用
WHERE筛选单个员工时,结果集只有该员工的薪资记录,自然能拿到他的上一条历史薪资; - 但查询所有员工时,结果集是所有员工的记录混排,
LAG()就会取物理上的上一行数据,而非同一个员工的历史薪资。
解决方案:用PARTITION BY按员工分组
你需要通过PARTITION BY把数据按员工唯一标识(比如emp_id)拆分,让LAG()只在当前员工的分组内取上一条记录,再配合ORDER BY按薪资生效时间排序,确保历史顺序正确。
示例代码
错误写法(无PARTITION BY):
SELECT emp_id, salary AS current_salary, LAG(salary) OVER (ORDER BY salary_effective_date) AS previous_salary, ROUND(((salary - LAG(salary) OVER (ORDER BY salary_effective_date))/LAG(salary) OVER (ORDER BY salary_effective_date))*100, 2) AS salary_change_pct FROM employee_salaries;
修正后写法:
SELECT emp_id, salary AS current_salary, -- 按员工分组,取该员工的上一条薪资 LAG(salary) OVER (PARTITION BY emp_id ORDER BY salary_effective_date) AS previous_salary, -- 处理无历史薪资的情况(避免除以NULL报错) ROUND( CASE WHEN LAG(salary) OVER (PARTITION BY emp_id ORDER BY salary_effective_date) IS NOT NULL THEN ((salary - LAG(salary) OVER (PARTITION BY emp_id ORDER BY salary_effective_date))/LAG(salary) OVER (PARTITION BY emp_id ORDER BY salary_effective_date))*100 ELSE NULL END, 2 ) AS salary_change_pct FROM employee_salaries;
额外提示
如果你的薪资表还有其他需要区分的维度(比如同一个员工有不同薪资类型),可以把这些字段也加到PARTITION BY里,保证分组逻辑完全匹配你的业务场景。
内容的提问来源于stack exchange,提问作者Cody J. Mathis
相关产品推荐
相关产品推荐

