MySQL内连接查询重复行问题求助(PHP考勤系统场景)
解决考勤系统中多签到签退的重复行问题
你的问题根源在于仅通过user_id和date关联签到签退表——当同一个用户同一天存在多次签到签退记录时,这种关联方式会触发笛卡尔积,把每一条签到记录和每一条签退记录都强行匹配一次,自然就出现了重复关联的错误行。
要解决这个问题,我们需要给同一天同一用户的签到、签退记录分别按时间排序并添加序号,然后通过user_id、date+序号来精准一一匹配,确保第一次签到对应第一次签退,第二次签到对应第二次签退。
修改后的SQL查询
SELECT b.name AS Name, c.user_id AS User_ID, c.date AS Date, a.time AS "Time In", c.time AS "Time Out", a.comment AS "Comment In", c.comment AS "Comment Out" FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY user_id, date ORDER BY time) AS checkout_seq FROM tbl_checkout ) c LEFT JOIN ( SELECT *, ROW_NUMBER() OVER (PARTITION BY user_id, date ORDER BY time) AS checkin_seq FROM tbl_checkin ) a ON c.user_id = a.user_id AND c.date = a.date AND c.checkout_seq = a.checkin_seq INNER JOIN tbl_userlogin b ON c.user_id = b.user_id ORDER BY c.date DESC, c.user_id, c.checkout_seq DESC;
核心逻辑解释
- 给记录添加分组序号:
- 对
tbl_checkout使用ROW_NUMBER()函数,按user_id和date分组,再按time升序排序,生成checkout_seq(签退序号) - 对
tbl_checkin做同样处理,生成checkin_seq(签到序号)
- 对
- 精准关联匹配:除了原有的
user_id和date,新增checkout_seq = checkin_seq作为关联条件,确保同序号的签到签退一一对应 - 排序优化:最后按日期倒序、用户ID、序号倒序排列,和你期望的结果顺序完全一致
这样修改后,UGT003的两条签到会分别对应两条签退,不会再出现错误关联的重复行,完全符合你想要的考勤日志展示效果。
内容的提问来源于stack exchange,提问作者yusgalaxy1996
相关产品推荐
相关产品推荐

