如何连接WorkerT与AttendanceT表,实现每个员工对应所有唯一LastDayMonth
解决员工与所有月末日期的出勤匹配问题
你的核心需求是让每个员工都对应所有存在的月末日期,有出勤记录就显示状态,没有则留空。之前直接用两张表做笛卡尔积的问题在于:AttendanceT里同一个日期可能对应多个员工的记录,导致笛卡尔积后同一个员工会重复匹配同一个日期多次,无法得到唯一的日期映射。
正确的思路是先提取出所有唯一的月末日期,再和员工表做交叉连接,最后左连接出勤表补全状态:
完整SQL语句
SELECT w.WorkerID, w.WorkerName, d.LastDayMonth, a.Attendance FROM WorkerT w CROSS JOIN (SELECT DISTINCT LastDayMonth FROM AttendanceT) d LEFT JOIN AttendanceT a ON w.WorkerID = a.WorkerID AND d.LastDayMonth = a.LastDayMonth ORDER BY w.WorkerID, d.LastDayMonth;
语句解释
(SELECT DISTINCT LastDayMonth FROM AttendanceT):先从出勤表中提取所有不重复的月末日期,得到一个干净的日期集合。CROSS JOIN:把员工表和这个唯一日期集合做笛卡尔积,生成「每个员工+每个日期」的基础组合,确保每个员工都能覆盖所有日期。LEFT JOIN AttendanceT:以基础组合为左表,关联出勤表,只有当员工ID和日期都匹配时才会带出Attendance值,不匹配的地方自动显示NULL。
示例验证
假设:
- WorkerT有两条记录:(1, '张三'), (2, '李四')
- AttendanceT有三条记录:(1, '2024-01-31', '正常'), (1, '2024-02-29', '迟到'), (2, '2024-01-31', '正常')
执行查询后会得到:
| WorkerID | WorkerName | LastDayMonth | Attendance |
|---|---|---|---|
| 1 | 张三 | 2024-01-31 | 正常 |
| 1 | 张三 | 2024-02-29 | 迟到 |
| 2 | 李四 | 2024-01-31 | 正常 |
| 2 | 李四 | 2024-02-29 | NULL |
这样就完美实现了每个员工对应所有唯一月末日期,缺失记录显示空的需求。
内容的提问来源于stack exchange,提问作者yehya Isa
相关产品推荐
相关产品推荐

