MySQL考勤表加班计算需求:周日及节假日全工时计为加班
考勤加班逻辑实现及方案选型
一、核心逻辑实现思路
基于需求,需在原有「每日工作超9小时部分计为加班(OTM)」的基础上,新增两个优先级更高的规则:
- 周日当日所有工作时长全额计为OTM
- 当日属于
holidays表中节假日的,所有工作时长全额计为OTM
关键判断条件
- 判断是否为周日:通过日期函数提取星期几,不同数据库语法略有差异:
- MySQL:
DAYOFWEEK(attdate) = 1(周日对应1) - SQL Server:
DATEPART(WEEKDAY, attdate) = 1(默认周日为一周第一天,若系统设置不同需调整) - PostgreSQL:
EXTRACT(DOW FROM attdate) = 0(周日对应0)
- MySQL:
- 判断是否为节假日:通过
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 直接计算插入
不建议采用先插入后更新的方式,原因如下:
- 性能损耗:两次数据库操作(插入+更新)会增加IO开销,数据量较大时锁竞争和事务耗时会明显上升
- 数据一致性风险:若插入后更新前出现异常(如数据库宕机),会导致
attTable中OTM值不符合规则,需额外补偿机制 - 逻辑冗余:所有判断逻辑可直接合并到插入语句的SELECT子句中,无需拆分步骤
除非业务存在特殊场景(如需先保留基础数据,后续再根据动态变化的节假日规则更新),否则优先选择直接在插入时完成OTM计算的方案,既高效又能保证数据一致性。
内容的提问来源于stack exchange,提问作者mafaz
相关产品推荐
相关产品推荐

