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

按日期透视DateTime字段:如何提取员工每日首次上班打卡记录?

获取员工每日首次上班打卡记录的SQL实现

针对你需要提取员工每日首次上班打卡(punch_type=1)记录的需求,这里提供两种实用的SQL方案,适配大多数主流关系型数据库(如MySQL、SQL Server、PostgreSQL等):

方法一:使用聚合函数MIN()(简洁高效)

如果只需要获取首次上班的打卡时间,这种方法最直接,通过过滤上班打卡记录后按员工+日期分组,取最小的打卡时间即可。

SELECT 
    emp_num,
    report_date,
    MIN(punch_time) AS first_punch_in_time
FROM 
    punch_records
WHERE 
    punch_type = 1  -- 仅筛选上班打卡类型
GROUP BY 
    emp_num, report_date
ORDER BY 
    emp_num, report_date;

说明:

  • 先通过WHERE punch_type=1过滤出所有上班打卡记录;
  • 按emp_num(员工编号)和report_date(打卡日期)分组,用MIN(punch_time)取出每组中最早的打卡时间;
  • 针对你提供的示例数据,执行后会得到员工1在2018-04-20的首次上班打卡时间为2018-04-20 04:46:00.000。

如果存在report_date和punch_time日期不一致的情况(比如跨天打卡),可以改用DATE(punch_time)作为分组依据,确保按实际打卡日期统计:

SELECT 
    emp_num,
    DATE(punch_time) AS actual_punch_date,
    MIN(punch_time) AS first_punch_in_time
FROM 
    punch_records
WHERE 
    punch_type = 1
GROUP BY 
    emp_num, DATE(punch_time)
ORDER BY 
    emp_num, actual_punch_date;

方法二:使用窗口函数ROW_NUMBER()(灵活扩展)

如果需要保留打卡记录的完整字段(比如后续要关联其他信息),或者处理有并列最早打卡的场景,窗口函数会更灵活。

WITH ranked_punches AS (
    SELECT 
        emp_num,
        report_date,
        punch_time,
        punch_type,
        -- 按员工+日期分组,按打卡时间升序标记行号
        ROW_NUMBER() OVER (
            PARTITION BY emp_num, report_date 
            ORDER BY punch_time ASC
        ) AS rn
    FROM 
        punch_records
    WHERE 
        punch_type = 1
)
SELECT 
    emp_num,
    report_date,
    punch_time AS first_punch_in_time,
    punch_type
FROM 
    ranked_punches
WHERE 
    rn = 1  -- 取每组中排名第一的记录(即首次打卡)
ORDER BY 
    emp_num, report_date;

说明:

  • 先用CTE(公共表表达式)给每个员工每天的上班打卡记录按时间排序并标记行号rn;
  • 筛选出行号为1的记录,就是该员工当日的首次上班打卡;
  • 如果存在同一时间多次上班打卡的情况,ROW_NUMBER()会随机返回其中一条,若要保留所有并列最早的记录,可以替换为RANK()或DENSE_RANK()。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:54:38