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

MySQL考勤表加班计算需求:周日及节假日全工时计为加班

考勤加班逻辑实现及方案选型

一、核心逻辑实现思路

基于需求,需在原有「每日工作超9小时部分计为加班(OTM)」的基础上,新增两个优先级更高的规则:

  • 周日当日所有工作时长全额计为OTM
  • 当日属于holidays表中节假日的,所有工作时长全额计为OTM

关键判断条件

  1. 判断是否为周日:通过日期函数提取星期几,不同数据库语法略有差异:
    • MySQL:DAYOFWEEK(attdate) = 1(周日对应1)
    • SQL Server:DATEPART(WEEKDAY, attdate) = 1(默认周日为一周第一天,若系统设置不同需调整)
    • PostgreSQL:EXTRACT(DOW FROM attdate) = 0(周日对应0)
  2. 判断是否为节假日:通过attendance.attdate与holidays.date_holiday的关联查询确认

插入SQL示例(以MySQL为例)

假设attendance表包含empid、attdate、work_hours(当日工作时长)字段,attTable包含empid、attdate、work_hours、otm字段:

INSERT INTO attTable (empid, attdate, work_hours, otm)
SELECT
    a.empid,
    a.attdate,
    a.work_hours,
    -- 优先判断周日或节假日,满足则全额计为OTM,否则按原规则计算
    CASE
        WHEN DAYOFWEEK(a.attdate) = 1 THEN a.work_hours
        WHEN EXISTS (SELECT 1 FROM holidays h WHERE h.date_holiday = a.attdate) THEN a.work_hours
        ELSE GREATEST(0, a.work_hours - 9)
    END AS otm
FROM attendance a;

如果你的数据库是SQL Server,只需调整星期判断函数:

INSERT INTO attTable (empid, attdate, work_hours, otm)
SELECT
    a.empid,
    a.attdate,
    a.work_hours,
    CASE
        WHEN DATEPART(WEEKDAY, a.attdate) = 1 THEN a.work_hours
        WHEN EXISTS (SELECT 1 FROM holidays h WHERE h.date_holiday = a.attdate) THEN a.work_hours
        ELSE IIF(a.work_hours > 9, a.work_hours - 9, 0)
    END AS otm
FROM attendance a;

二、方案选型:先插入后更新 vs 直接计算插入

不建议采用先插入后更新的方式,原因如下:

  1. 性能损耗:两次数据库操作(插入+更新)会增加IO开销,数据量较大时锁竞争和事务耗时会明显上升
  2. 数据一致性风险:若插入后更新前出现异常(如数据库宕机),会导致attTable中OTM值不符合规则,需额外补偿机制
  3. 逻辑冗余:所有判断逻辑可直接合并到插入语句的SELECT子句中,无需拆分步骤

除非业务存在特殊场景(如需先保留基础数据,后续再根据动态变化的节假日规则更新),否则优先选择直接在插入时完成OTM计算的方案,既高效又能保证数据一致性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 02:05:12