SQL Server中如何按员工分组配对打卡数据并排序?
考勤记录配对解决方案
针对你的需求,我们可以通过窗口函数+自连接的方式实现打卡记录的成对输出,同时兼容打卡次数不固定和漏打卡的情况。以下是具体实现步骤:
1. 给打卡记录排序编号
先用ROW_NUMBER()窗口函数按员工分组,再按打卡日期和时间排序,给每条记录分配一个序号,把同一员工的打卡记录按时间顺序排列,方便后续配对。
WITH ranked_attendance AS ( SELECT EmployeeID, Date, Time, -- 按员工分组,日期+时间排序生成序号 ROW_NUMBER() OVER ( PARTITION BY EmployeeID ORDER BY STR_TO_DATE(Date, '%m/%d/%y'), STR_TO_DATE(Time, '%H:%i') ) AS rn FROM attendance_table )
注:如果你的数据库不是MySQL,需要调整日期转换函数:
- SQL Server:用
CONVERT(DATE, Date, 101)和CONVERT(TIME, Time)- PostgreSQL:用
TO_DATE(Date, 'MM/DD/YY')和TO_TIME(Time)
2. 配对IN/OUT记录
将序号为奇数的记录(视为上班打卡IN)和下一条序号为偶数的记录(视为下班打卡OUT)通过自连接配对,最后拼接成你需要的格式,同时处理漏打卡的情况。
SELECT CONCAT( a.EmployeeID, '-', a.Date, '-', a.Time, '-', -- 漏打卡时显示"未打卡",避免空值 COALESCE(b.Date, '未打卡'), '-', COALESCE(b.Time, '未打卡') ) AS attendance_pair FROM ranked_attendance a LEFT JOIN ranked_attendance b ON a.EmployeeID = b.EmployeeID AND a.rn + 1 = b.rn -- 只取奇数序号的记录,确保每一行对应一组IN-OUT WHERE a.rn % 2 = 1;
效果说明
- 针对你的示例输入,执行后会输出预期结果:
12345-8/25/22-08:45-8/25/22-09:45 12345-8/25/22-13:00-8/25/22-13:30 23456-8/25/22-10:00-8/25/22-11:00 - 若员工存在漏打卡(比如只有3条记录),最后一组的下班字段会显示"未打卡",不会丢失数据。
内容的提问来源于stack exchange,提问作者Fusic
相关产品推荐
相关产品推荐

