SQL如何按员工连续任职岗位分组提取每组的最大行记录
解法思路
这是典型的SQL连续序列分组(岛屿问题),核心是给相邻且岗位相同的记录生成相同的分组标识,即可避免非连续的相同岗位被分到同一组。
实现步骤
- 第一步:给所有记录按任职开始时间
StDt升序排序,生成全局连续行号 - 第二步:按岗位
Job分区,每个岗位下同样按StDt升序排序,生成岗位内的连续行号 - 第三步:计算分组标识 = 全局行号 - 岗位内行号。连续的相同岗位的分组标识值会完全一致,岗位切换后分组标识会跳变,即便后续回到同一岗位,新的分组标识也不会和之前的同岗位分组重复
- 第四步:按分组标识分组,每组内取
EdDt最大(也就是任职结束时间最晚)的记录即可
示例代码(支持窗口函数的数据库通用,如MySQL8.0+、Oracle、PostgreSQL、SQL Server等)
WITH ranked_data AS ( SELECT *, -- 全局行号,按开始时间排序 ROW_NUMBER() OVER(ORDER BY StDt ASC) AS rn_total, -- 每个岗位内部的行号 ROW_NUMBER() OVER(PARTITION BY Job ORDER BY StDt ASC) AS rn_job FROM emp_job_records -- 此处替换为你的实际表名 ), grouped_data AS ( SELECT *, -- 计算连续分组标识 rn_total - rn_job AS job_grp FROM ranked_data ) SELECT StDt, EdDt, Job FROM ( SELECT *, -- 每个分组内按结束时间倒序,取第一条即为每组的最大行 ROW_NUMBER() OVER(PARTITION BY job_grp ORDER BY EdDt DESC) AS rn_grp FROM grouped_data ) t WHERE rn_grp = 1;
如果表内包含多名员工的任职记录,只需在所有窗口函数的OVER参数中增加PARTITION BY 员工ID字段,即可实现多员工的批量分组提取。
结果验证
执行后会得到你需要的3条目标记录:
| StDt | EdDt | Job |
|---|---|---|
| 1-Feb-21 | 30-Jun-21 | J1 |
| 16-Aug-21 | 31-Aug-21 | J2 |
| 2-Nov-21 | 31-Dec-21 | J1 |
内容的提问来源于stack exchange,提问作者Alka Ojha
相关产品推荐
相关产品推荐

