CodeIgniter查询构造器关联逗号分隔字段实现技能费用统计
问题根因定位
- 核心查询逻辑缺陷:查询Schedule表时调用
row('Do_skill'),仅能返回时间范围内匹配的第一条排班记录的技能列表,所有后续排班记录中的技能会被完全遗漏,自然无法匹配到对应价格,累加结果远低于预期。 - 字符串清洗缺失:逗号分隔转数组的方法未对拆分后的技能名做
trim去空格处理,例如排班字段中"Engineering, Freelancer"拆分出的带前置空格的" Freelancer",无法和skillqmount表中无空格的标准技能名Freelancer匹配,导致对应价格漏算。 - 数值计算失效:
skillqmount表的Price字段存储为带$符号、空格的字符串(如$ 5),直接调用select_sum('price')会因为字段为字符串类型无法正确累加数值,结果不符合预期。 - 边界匹配遗漏:原代码对结束日期使用
<比较,会漏掉日期恰好等于结束日期的排班记录、价格记录,和业务预期的“选定时间段内”的统计范围不匹配。
修正后的完整实现
首先替换Check_model中的字符串处理方法:
public function comma_separated_to_array($chck, $separator = ','){ if (empty($chck)) { return []; } $raw_vals = explode($separator, $chck); $clean_vals = []; foreach ($raw_vals as $val) { // 去除前后多余空格,过滤空值 $trimmed_val = trim($val); if ($trimmed_val !== '') { $clean_vals[] = $trimmed_val; } } // 单条排班内的技能去重,减少冗余匹配 return array_unique($clean_vals); }
再替换控制器端的业务逻辑:
<?php $startd = $this->input->post('A'); $endd = $this->input->post('B'); // 步骤1:收集选定时间段内所有排班记录的关联技能 $schedule_res = $this->db ->select('Do_skill') ->where('Activ_date >=', $startd) ->where('Activ_date <=', $endd) // 根据业务调整边界,如需排除当天可改回< ->get('Schedule'); $matched_skills = []; if ($schedule_res->num_rows() > 0) { foreach ($schedule_res->result() as $schedule_row) { $row_skills = $this->Check_model->comma_separated_to_array($schedule_row->Do_skill); $matched_skills = array_merge($matched_skills, $row_skills); } // 全局技能去重,避免where_in冗余 $matched_skills = array_unique($matched_skills); } // 无匹配技能时直接返回0 if (empty($matched_skills)) { echo '$0'; exit; } // 步骤2:清洗价格字段后做累加统计,匹配时间段内对应技能的价格 $total_amount = $this->db // 把带$、空格的字符串价格转为数值再求和 ->select_sum("CAST(REPLACE(REPLACE(price, '$', ''), ' ', '') AS DECIMAL(10,2))", 'total_price') ->where('Date_skill >=', $startd) ->where('Date_skill <=', $endd) ->where_in('Skill', $matched_skills) ->get('skillqmount') ->row('total_price'); // 格式化输出结果 echo '$' . number_format((float)$total_amount, 2);
实现说明
- 全量技能收集:不再仅取第一条排班的技能,而是遍历时间范围内所有排班记录,把所有关联技能汇总去重后再做匹配,解决原逻辑漏算技能的问题。
- 技能名标准化:拆分逗号字符串时同步去除前后空格,保证和skillqmount表的标准技能名格式完全一致,避免格式不匹配导致的漏算。
- 价格字段清洗:通过SQL内的
REPLACE、CAST操作把字符串类型的带符号价格转为纯数值类型,再执行求和,解决字符串无法累加的问题。 - 边界可配置:根据业务实际统计范围调整日期比较的运算符,示例中使用
<=保证结束日期当天的记录被纳入统计。
内容的提问来源于stack exchange,提问作者karisma
相关产品推荐
相关产品推荐

