You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

对比两个数据表的日期时间,查询员工未出勤的班次

我来帮你解决这个问题哈~要找出员工未出勤的班次,核心就是对比班次表和考勤表,筛选出那些没有对应有效出勤记录的班次。先把你的示例表补全,方便咱们测试演示:

完整示例表创建
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:37:13