如何用CodeIgniter 4 Query Builder合并同employee_id的考勤记录行
CodeIgniter 4 Query Builder 合并考勤记录实现方案
针对你需要将同一employee_id的in/out两条考勤记录合并为一行的需求,推荐两种高效实现方式,替代CONCAT的思路:
方法一:条件聚合(推荐,适配多场景)
利用SQL条件聚合函数,按employee_id分组后提取对应状态的时间,这是处理行转列需求的标准方案,适配员工多次打卡的场景。
模型代码示例
public function getMergedAttendance() { return $this->db->table('attendance') // 取同一员工最早的记录id作为合并后的id,可根据业务调整为MAX(id) ->select('MIN(id) as id, employee_id, MAX(CASE WHEN in_out = "in" THEN time END) as `in`, MAX(CASE WHEN in_out = "out" THEN time END) as `out`') ->groupBy('employee_id') ->get() ->getResult(); }
扩展:按日期分组(若需每日统计)
如果需要按「员工+日期」维度合并(比如员工一天内多次打卡),只需在分组和查询中加入日期维度:
public function getDailyMergedAttendance() { return $this->db->table('attendance') ->select('MIN(id) as id, employee_id, DATE(time) as attendance_date, MAX(CASE WHEN in_out = "in" THEN time END) as `in`, MAX(CASE WHEN in_out = "out" THEN time END) as `out`') ->groupBy('employee_id, DATE(time)') ->get() ->getResult(); }
方法二:自连接(适合固定单条in/out场景)
如果确定每个员工仅对应一条in和一条out记录,可以用自连接关联两张虚拟表,直接匹配对应状态的记录。
模型代码示例
public function getAttendanceByJoin() { return $this->db->table('attendance a_in') ->select('a_in.id, a_in.employee_id, a_in.time as `in`, a_out.time as `out`') // 左连接确保即使没有out记录也能保留in记录 ->join('attendance a_out', 'a_in.employee_id = a_out.employee_id AND a_out.in_out = "out"', 'left') ->where('a_in.in_out', 'in') ->get() ->getResult(); }
注意事项
- 若
time字段是字符串类型,确保格式统一,避免聚合或连接时出现异常; - 可根据业务需求调整
MIN(id)为其他逻辑(比如固定取in状态的id); - 两种方法均支持添加额外
where条件(比如按时间范围筛选),直接在Query Builder链中追加即可。
内容的提问来源于stack exchange,提问作者asnka go
相关产品推荐
相关产品推荐

