如何用SQL将两张关联表的两行记录合并为一行?
实现员工考勤记录合并为单行的SQL方案
针对你给出的员工表(peg)和考勤表(absen),要把同一个员工的当日考勤IN/OUT记录合并成一行,这里提供两种实用的SQL写法:
方法一:使用聚合函数 + CASE WHEN(适合多记录场景)
这种方法可以处理一个员工当日可能有多条IN/OUT记录的情况(比如多次打卡),会自动提取对应的目标记录(示例用MAX取最晚的,若要最早的IN可换成MIN):
SELECT p.id, p.name, p.kode, MAX(CASE WHEN a.ket = 'IN' THEN a.time END) AS time_1, MAX(CASE WHEN a.ket = 'IN' THEN a.ket END) AS ket, MAX(CASE WHEN a.ket = 'OUT' THEN a.time END) AS time_2, MAX(CASE WHEN a.ket = 'OUT' THEN a.ket END) AS ket FROM peg p JOIN absen a ON p.kode = a.kode GROUP BY p.id, p.name, p.kode, DATE(a.time);
逻辑说明:
- 通过
JOIN关联员工表和考勤表,匹配员工的kode字段 - 用
CASE WHEN分别筛选出IN和OUT类型的考勤记录,再通过MAX聚合函数提取对应时间和状态 - 按员工信息+考勤日期分组,确保同一员工同一天的记录合并成一行
方法二:使用自连接(适合固定一对IN/OUT场景)
如果确定每个员工每天只有一条IN和一条OUT记录,用自连接会更简洁直接:
SELECT p.id, p.name, p.kode, a_in.time AS time_1, a_in.ket AS ket, a_out.time AS time_2, a_out.ket AS ket FROM peg p JOIN absen a_in ON p.kode = a_in.kode AND a_in.ket = 'IN' JOIN absen a_out ON p.kode = a_out.kode AND a_out.ket = 'OUT' -- 确保IN和OUT是同一天的记录 AND DATE(a_in.time) = DATE(a_out.time);
逻辑说明:
- 把考勤表拆成两个虚拟表:
a_in只存IN记录,a_out只存OUT记录 - 通过员工
kode和日期关联这两个虚拟表,直接把对应字段拼接成一行
两种方法都能得到你需要的结果格式,根据你的实际数据情况选择就好~
内容的提问来源于stack exchange,提问作者gagah gelap
相关产品推荐
相关产品推荐

