PostgreSQL如何去重重复考勤记录并提取有效时间更新排班表
解答
完全可以通过纯PostgreSQL SQL实现需求,具体方案如下:
取值规则对齐
根据你的描述,先明确四个时段的打卡取数逻辑,完全匹配你的要求:
- 上班打卡(
attendance_start_time):取当日早于start_lunch的所有打卡,取最大值(多次打卡均早于上班时间时取最晚的有效早到记录,取最小也可,只需把MAX改成MIN即可) - 午餐开始打卡(
attendance_start_lunch):取当日大于等于start_lunch、小于end_lunch的所有打卡,取最大值(完全符合你要求的“大于start_lunch的最大时间”规则) - 午餐结束打卡(
attendance_end_lunch):取当日大于start_lunch、小于等于end_lunch的所有打卡,取最小值(取最早结束午餐的有效记录) - 下班打卡(
attendance_end_time):取当日晚于end_lunch的所有打卡,取最小值(多次打卡均晚于下班时间时取最早的离岗记录,也可根据需求改为最大值)
注:你给出的
Attendance表字段定义写的是attendance_hour,但示例数据字段为attendance_time,以下SQL以示例的attendance_time为准,若实际字段名不同请自行替换。
实现SQL
WITH attendance_calc AS ( -- 先按员工+日期分组,计算四个时段的有效打卡时间 SELECT a.employee_code, a.attendance_date AS work_date, -- 上班有效打卡 MAX(CASE WHEN a.attendance_time < w.start_lunch THEN a.attendance_time END) AS valid_start_time, -- 午餐开始有效打卡 MAX(CASE WHEN a.attendance_time >= w.start_lunch AND a.attendance_time < w.end_lunch THEN a.attendance_time END) AS valid_start_lunch, -- 午餐结束有效打卡 MIN(CASE WHEN a.attendance_time > w.start_lunch AND a.attendance_time <= w.end_lunch THEN a.attendance_time END) AS valid_end_lunch, -- 下班有效打卡 MIN(CASE WHEN a.attendance_time > w.end_lunch THEN a.attendance_time END) AS valid_end_time FROM Attendance a INNER JOIN Working_date w ON a.employee_code = w.employee_code AND a.attendance_date = w.work_date GROUP BY a.employee_code, a.attendance_date ) -- 将计算结果更新到Working_date表对应字段 UPDATE Working_date w SET attendance_start_time = c.valid_start_time, attendance_start_lunch = c.valid_start_lunch, attendance_end_lunch = c.valid_end_lunch, attendance_end_time = c.valid_end_time FROM attendance_calc c WHERE w.employee_code = c.employee_code AND w.work_date = c.work_date;
验证建议
你可以先单独执行CTE部分的SELECT语句,核对计算出来的四个有效时间是否符合预期,确认规则无误后再执行完整的UPDATE操作。如果有特殊的边界判断需求,直接调整CASE WHEN里的时间条件即可。
内容的提问来源于stack exchange,提问作者Fabyc
相关产品推荐
相关产品推荐

