如何计算同列中员工最近两条考勤记录的日期差(天数)
解决思路:用窗口函数简化日期差计算
你已经成功用ROW_NUMBER()拿到了每个员工最近两条考勤记录,卡在日期差计算上很正常——自关联确实容易踩坑,比如关联条件没精准匹配到对应的相邻记录,或者日期转换时格式不对导致计算错误。试试用窗口函数来解决,逻辑更清晰,也不容易出错。
问题分析
你之前尝试自关联计算日期差,但结果不正确,大概率是两个原因:
- 自关联时没有限定只取同员工的最近两条记录,导致匹配到了更早的考勤数据;
- 日期转换时没指定正确的格式掩码,数据库解析日期出错,进而差值计算错误。
解决方案
方案1:每条记录都显示两条的日期差(符合你的第一个期望输出)
用MAX()和MIN()窗口函数,在同员工分区内直接计算最近两条记录的日期差,然后过滤出前两条记录即可:
SELECT T1.EMPNO AS Id, T1.ATT_DATE AS Date, -- 计算当前员工最近两条考勤的日期差 TRUNC( MAX(TO_DATE(T1.ATT_DATE, 'MM/DD/YYYY')) OVER(PARTITION BY T1.EMPNO) - MIN(TO_DATE(T1.ATT_DATE, 'MM/DD/YYYY')) OVER(PARTITION BY T1.EMPNO) ) AS Days FROM ( SELECT T2.EMPNO, T2.ATT_DATE, ROW_NUMBER() OVER(PARTITION BY T2.EMPNO ORDER BY TO_DATE(T2.ATT_DATE, 'MM/DD/YYYY') DESC) AS rn FROM TableName T2 ) T1 WHERE T1.rn <= 2 ORDER BY T1.EMPNO, TO_DATE(T1.ATT_DATE, 'MM/DD/YYYY') DESC;
方案2:只在最新记录显示日期差(符合你的更新1期望输出)
用LAG()窗口函数直接获取同员工的上一条考勤日期,然后只保留最新的那条记录:
SELECT T1.EMPNO AS Id, T1.ATT_DATE AS Date, TRUNC( TO_DATE(T1.ATT_DATE, 'MM/DD/YYYY') - TO_DATE(T1.prev_att_date, 'MM/DD/YYYY') ) AS Days FROM ( SELECT T2.EMPNO, T2.ATT_DATE, ROW_NUMBER() OVER(PARTITION BY T2.EMPNO ORDER BY TO_DATE(T2.ATT_DATE, 'MM/DD/YYYY') DESC) AS rn, -- 获取同员工的上一条考勤日期 LAG(T2.ATT_DATE) OVER(PARTITION BY T2.EMPNO ORDER BY TO_DATE(T2.ATT_DATE, 'MM/DD/YYYY') DESC) AS prev_att_date FROM TableName T2 ) T1 WHERE T1.rn = 1 -- 只保留最新的考勤记录 AND T1.prev_att_date IS NOT NULL; -- 确保存在上一条记录
关键注意点
- 日期格式掩码:一定要在
TO_DATE()里指定格式'MM/DD/YYYY',因为你的日期是1/24/2018这种月/日/年的格式,如果数据库默认格式不匹配,会导致日期解析错误,差值自然不对; - 窗口函数的分区与排序:所有窗口函数都要按
EMPNO分区,按日期降序排序,这样才能精准匹配到同员工的相邻记录。
内容的提问来源于stack exchange,提问作者user8512043
相关产品推荐
相关产品推荐

