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

MySQL考勤表日期范围查询:关联IN/OUT记录并补全日期

MySQL考勤记录按日期范围查询并匹配IN/OUT规则的SQL语句

表结构与示例数据

考勤表attendance的结构及示例数据如下:

EmployeeDate_TimeStatus
std0012024-02-01 22:01:00IN
std0012024-02-02 06:00:05OUT
std0012024-02-03 07:59:00IN
std0012024-02-03 17:00:00OUT
std0012024-02-04 06:00:00IN
std0012024-02-04 14:00:00OUT

查询规则

  1. DateTime_In取自Status = 'IN'的Date_Time字段值
  2. 若DateTime_In的时间部分**< 22:00:00**,DateTime_Out取当日Status = 'OUT'的Date_Time
  3. 若DateTime_In的时间部分**>= 22:00:00**,DateTime_Out取次日Status = 'OUT'的Date_Time
  4. 指定日期范围内无对应记录的日期,所有字段显示NULL
  5. 2024-02-02这类跨天考勤记录的三种可接受格式已被规则覆盖,无需额外处理

MySQL查询语句

WITH date_range AS (
    -- 替换此处的起止日期以调整查询范围
    SELECT DATE('2024-02-01') AS att_date
    UNION ALL
    SELECT att_date + INTERVAL 1 DAY
    FROM date_range
    WHERE att_date < DATE('2024-02-05')
)
SELECT
    dr.att_date,
    a_in.Employee,
    a_in.Date_Time AS DateTime_In,
    -- 根据上班打卡时间匹配对应下班记录
    CASE
        WHEN TIME(a_in.Date_Time) < '22:00:00' THEN a_out_same.Date_Time
        ELSE a_out_next.Date_Time
    END AS DateTime_Out
FROM date_range dr
LEFT JOIN attendance a_in
    ON dr.att_date = DATE(a_in.Date_Time) AND a_in.Status = 'IN'
-- 关联当日下班记录
LEFT JOIN attendance a_out_same
    ON dr.att_date = DATE(a_out_same.Date_Time) 
    AND a_out_same.Status = 'OUT'
    AND a_out_same.Employee = a_in.Employee
-- 关联次日下班记录
LEFT JOIN attendance a_out_next
    ON (dr.att_date + INTERVAL 1 DAY) = DATE(a_out_next.Date_Time) 
    AND a_out_next.Status = 'OUT'
    AND a_out_next.Employee = a_in.Employee
ORDER BY dr.att_date;

语句说明

  1. 日期序列生成:通过递归CTE date_range生成指定起止日期之间的所有日期,确保无考勤记录的日期也能出现在结果中
  2. 关联上班记录:用LEFT JOIN匹配对应日期的上班打卡(Status='IN')记录
  3. 匹配下班记录:根据上班打卡时间的早晚,分别关联当日或次日的下班打卡(Status='OUT')记录
  4. 空值处理:LEFT JOIN保证即使某日期无考勤数据,仍会显示该日期,对应字段自动填充NULL

内容的提问来源于stack exchange,提问作者Yohan Wijayanto

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 19:32:49