You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

SQL新手求助:将考勤打卡记录表转换为上下班时间格式的查询语句

解决考勤数据行转列的SQL查询方案

嘿,作为SQL新手碰到这种把多行打卡记录合并成一行的需求太常见啦,我来一步步帮你实现想要的结果~

首先看你的原始数据,每个员工每天有两条打卡记录:一条上班时间,一条下班时间。我们的目标就是把同一天的两条记录合并,分别提取出上班(ATTINTIME)和下班(ATTOUTTIME)时间。

方法一:用聚合函数(最适合你的场景)

因为你每天只有两次打卡,直接用MIN()取最早的时间作为上班,MAX()取最晚的时间作为下班就可以了,配合GROUP BY按员工和日期分组:

SELECT 
    EMP_NUMBER,
    ATTDATE,
    MIN(ATTTIME) AS ATTINTIME,
    MAX(ATTTIME) AS ATTOUTTIME
FROM 
    你的考勤表名
GROUP BY 
    EMP_NUMBER, ATTDATE;

解释

  • GROUP BY EMP_NUMBER, ATTDATE 把数据按员工+日期分组,确保每个组里是同一个人同一天的所有打卡记录
  • MIN(ATTTIME) 找出组里最早的打卡时间,也就是上班时间
  • MAX(ATTTIME) 找出组里最晚的打卡时间,也就是下班时间

方法二:用窗口函数(应对更复杂的打卡场景)

如果某天员工有多次打卡(比如中途外出又返回),你需要明确区分第一次和第二次打卡的话,可以用ROW_NUMBER()窗口函数给每条记录排序,再通过条件筛选提取:

WITH RankedAttendance AS (
    SELECT 
        EMP_NUMBER,
        ATTDATE,
        ATTTIME,
        ROW_NUMBER() OVER (PARTITION BY EMP_NUMBER, ATTDATE ORDER BY ATTTIME) AS rn
    FROM 
        你的考勤表名
)
SELECT 
    EMP_NUMBER,
    ATTDATE,
    MAX(CASE WHEN rn = 1 THEN ATTTIME END) AS ATTINTIME,
    MAX(CASE WHEN rn = 2 THEN ATTTIME END) AS ATTOUTTIME
FROM 
    RankedAttendance
GROUP BY 
    EMP_NUMBER, ATTDATE;

解释

  • 先通过CTE给每个员工每天的打卡记录按时间排序,rn=1是最早的打卡,rn=2是第二次打卡
  • 然后用CASE WHEN配合MAX()把不同排序的时间放到对应的列里

把上面的你的考勤表名替换成你实际的表名,就能得到你想要的结果啦~

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

火山引擎 最新活动