在员工薪资管理的相关数据统计中,计算每名员工在部门内的调薪幅度是常见需求,这个需求可以通过SQL的LAG窗口函数高效实现,不需要复杂的自连接操作。

LAG函数基本说明
LAG函数是SQL中常用的窗口函数,作用是获取当前行之前指定偏移量的行的数据。它的基本语法如下:
LAG(列名, 偏移量, 默认值) OVER (PARTITION BY 分组列 ORDER BY 排序列)
参数说明:
- 列名:要获取的列的值
- 偏移量:往前取第几行的数据,默认是1
- 默认值:如果往前没有对应行时返回的值,默认是NULL
- PARTITION BY:指定分组的列,相同值的行分为一组单独计算
- ORDER BY:指定组内的排序规则
场景准备与表结构
假设我们有员工调薪记录表salary_record,表结构如下:
| 字段名 | 类型 | 说明 |
|---|---|---|
| emp_id | INT | 员工ID |
| dept_id | INT | 部门ID |
| salary | DECIMAL(10,2) | 调薪后的薪资 |
| adjust_date | DATE | 调薪日期 |
表中存储了每名员工每次调薪的记录,同一名员工可能有多次调薪记录,现在需要计算每名员工每次调薪相对上一次调薪的幅度,并且按部门分组计算。
完整计算SQL实现
我们可以通过LAG函数获取每名员工上一次的薪资,再结合当前薪资计算调薪幅度,完整SQL如下:
SELECT
emp_id AS 员工ID,
dept_id AS 部门ID,
adjust_date AS 调薪日期,
salary AS 当前薪资,
-- 获取同一部门内同一员工上一次的薪资,没有上一次记录则返回NULL
LAG(salary, 1, NULL) OVER (
PARTITION BY dept_id, emp_id
ORDER BY adjust_date
) AS 上一次薪资,
-- 计算调薪幅度,公式为(当前薪资-上一次薪资)/上一次薪资*100%
CASE
WHEN LAG(salary, 1, NULL) OVER (
PARTITION BY dept_id, emp_id
ORDER BY adjust_date
) IS NULL THEN NULL
ELSE ROUND(
(salary - LAG(salary, 1, NULL) OVER (
PARTITION BY dept_id, emp_id
ORDER BY adjust_date
)) / LAG(salary, 1, NULL) OVER (
PARTITION BY dept_id, emp_id
ORDER BY adjust_date
) * 100,
2
)
END AS 调薪幅度百分比
FROM salary_record
ORDER BY dept_id, emp_id, adjust_date;
结果说明
执行上述SQL后,会得到每条调薪记录对应的上一次薪资和调薪幅度:
- 如果是该员工在部门内的第一条调薪记录,上一次薪资为NULL,调薪幅度也为NULL
- 后续调薪记录会显示上一次的薪资数值,以及本次调薪的幅度百分比,正数表示涨薪,负数表示降薪
如果只需要计算有上一次调薪记录的幅度,可以在外层加WHERE条件过滤掉上一次薪资为NULL的记录。
注意事项
使用LAG函数时,PARTITION BY的分组条件要和实际需求匹配,这里需要同时按部门和员工分组,避免不同员工的薪资记录互相干扰。
排序字段要根据调薪的时间顺序来定,确保取到的是上一次的调薪记录,而不是其他时间的记录。如果调薪日期有重复,可以额外增加排序字段比如调薪记录ID来保证顺序唯一。