对比两个数据表的日期时间,查询员工未出勤的班次
我来帮你解决这个问题哈~要找出员工未出勤的班次,核心就是对比班次表和考勤表,筛选出那些没有对应有效出勤记录的班次。先把你的示例表补全,方便咱们测试演示:
完整示例表创建
DECLARE @InsideOutsideTable TABLE ( FromTime DATETIME, ToTime DATETIME ) DECLARE @ShiftTable TABLE ( FromDateTime DATETIME, ToDateTime DATETIME ) -- 插入班次数据 INSERT INTO @ShiftTable VALUES ('2018-05-02 07:30:00.000','2018-05-02 12:30:00.000') INSERT INTO @ShiftTable VALUES ('2018-05-02 01:30:00.000','2018-05-02 16:30:00.000') INSERT INTO @ShiftTable VALUES ('2018-05-03 08:00:00.000','2018-05-03 17:00:00.000') -- 插入考勤数据(第一条对应第一个班次,第二条无匹配班次) INSERT INTO @InsideOutsideTable VALUES ('2018-05-02 07:40:00.000','2018-05-02 12:20:00.000') INSERT INTO @InsideOutsideTable VALUES ('2018-05-02 17:00:00.000','2018-05-02 22:00:00.000')
查询未出勤班次的两种实用方法
方法1:使用NOT EXISTS(推荐,性能更优)
这个方法直接筛选出没有任何考勤记录与班次时间重叠的班次,逻辑清晰且效率较高:
SELECT s.FromDateTime AS 班次开始时间, s.ToDateTime AS 班次结束时间 FROM @ShiftTable s WHERE NOT EXISTS ( SELECT 1 FROM @InsideOutsideTable i -- 判断考勤时间和班次时间是否存在重叠 WHERE i.FromTime < s.ToDateTime AND i.ToTime > s.FromDateTime )
逻辑说明:
- 子查询会检查当前班次是否有对应的重叠考勤记录
- 如果子查询返回空(也就是没有找到匹配的考勤),那这个班次就是未出勤的
方法2:使用LEFT JOIN + IS NULL
通过左连接保留所有班次记录,再筛选出没有匹配到考勤的行:
SELECT s.FromDateTime AS 班次开始时间, s.ToDateTime AS 班次结束时间 FROM @ShiftTable s LEFT JOIN @InsideOutsideTable i ON i.FromTime < s.ToDateTime AND i.ToTime > s.FromDateTime WHERE i.FromTime IS NULL
逻辑说明:
- 左连接会保留
ShiftTable里的所有班次,哪怕没有对应的考勤记录 - 筛选出考勤表字段为
NULL的行,就是没有出勤记录的班次
测试结果
运行上面的查询后,会得到以下未出勤的班次:
班次开始时间 班次结束时间 ----------------------- ----------------------- 2018-05-02 01:30:00.000 2018-05-02 16:30:00.000 2018-05-03 08:00:00.000 2018-05-03 17:00:00.000
这两个班次就是没有对应有效出勤记录的未出勤班次啦~
内容的提问来源于stack exchange,提问作者good-to-know
相关产品推荐
相关产品推荐

