两列求和结果异常:生产与缺陷报表数据聚合错误
问题原因
多表关联时,production_report的单条生产记录会被production_defects_report中对应型号+工序的多条缺陷记录重复关联,导致SUM(pr.pro_qty)被重复累加(重复次数等于对应缺陷记录的数量),最终生产数量统计值偏大。
修正方案
通过预聚合生产数据的方式,先计算出每个型号+工序的总生产数量,再关联缺陷表统计缺陷数据,从根源避免行重复导致的计算错误。同时添加缺陷占比计算,并用左连接确保无缺陷的工序也能纳入报表:
public function getCombinedReport() { // 子查询预计算各型号+工序的总生产数量 $prodSubquery = $this->db->select('pro_model_id, pro_stage_id, SUM(pro_qty) AS total_pro_qty') ->from('production_report') ->group_by('pro_model_id, pro_stage_id') ->get_compiled_select(); // 关联所有表并统计缺陷数据,计算占比 $this->db->select(' md.modet_desc AS model_name, s.st_name AS stage_name, pr_total.total_pro_qty, COALESCE(d.def_name, "无缺陷") AS defect_name, COALESCE(SUM(pdr.pdr_qty), 0) AS total_pdr_qty, // 处理除数为0的情况,避免报错 CASE WHEN pr_total.total_pro_qty = 0 THEN 0 ELSE ROUND(COALESCE(SUM(pdr.pdr_qty), 0)/pr_total.total_pro_qty*100, 2) END AS defect_ratio ') ->from("($prodSubquery) AS pr_total") ->join('model_details AS md', 'pr_total.pro_model_id = md.modet_id') ->join('stages AS s', 'pr_total.pro_stage_id = s.st_id') // 左连接保留无缺陷的工序记录 ->join('production_defects_report AS pdr', 'pr_total.pro_model_id = pdr.pdr_modet_id AND pr_total.pro_stage_id = pdr.pdr_stage_id', 'left') ->join('defects AS d', 'pdr.pdr_defect_id = d.def_id', 'left') ->group_by('pr_total.pro_model_id, pr_total.pro_stage_id, d.def_id'); $query = $this->db->get(); return $query->result(); }
关键说明
- 预聚合生产数据:子查询先完成
production_report的分组求和,确保每个型号+工序只有一行总生产数量数据,后续关联缺陷表时不会被重复计算。 - 左连接的使用:避免过滤掉没有缺陷记录的工序,保证报表完整性,无缺陷时缺陷名称显示为"无缺陷",数量为0。
- 占比容错处理:通过
CASE语句处理生产数量为0的情况,避免出现除以0的SQL错误。
内容的提问来源于stack exchange,提问作者Syam
相关产品推荐
相关产品推荐

