Laravel中Join、Sum与Group by查询求和值超出预期问题
解决Laravel中数据库查询求和结果超出预期的问题
原查询的问题在于:institutes和enrollements是一对多关联,直接join会生成重复的enrollements记录,执行sum时会重复累加同一机构的男女数,导致结果偏大。
修正后的查询代码(DB门面方式)
$dist_total_gender = DB::table('institutes') // 先子查询统计每个机构的男女总数,避免重复行 ->join(DB::raw('( SELECT form_id, SUM(total_boys) AS institute_total_boys, SUM(total_girls) AS institute_total_girls FROM enrollements GROUP BY form_id ) AS enrollement_totals'), function($join) { $join->on('enrollement_totals.form_id', '=', 'institutes.form_id'); }) ->join('Geographies', 'institutes.district', '=', 'Geographies.id') ->groupBy('institutes.district', 'Geographies.name') ->select( DB::raw('SUM(enrollement_totals.institute_total_boys) AS Total_Boys'), DB::raw('SUM(enrollement_totals.institute_total_girls) AS Total_Girls'), DB::raw('Geographies.name AS District') ) ->get();
基于Eloquent模型的简化方式(若定义了模型关联)
假设你已经在Institute模型中定义了与Enrollment的关联:
// Institute.php public function enrollments() { return $this->hasMany(Enrollment::class, 'form_id'); }
则可以用withSum直接统计每个机构的男女数,再按地区汇总:
$dist_total_gender = Institute::query() ->withSum('enrollments', 'total_boys') ->withSum('enrollments', 'total_girls') ->join('Geographies', 'institutes.district', '=', 'Geographies.id') ->groupBy('institutes.district', 'Geographies.name') ->select( DB::raw('SUM(enrollments_total_boys_sum) AS Total_Boys'), DB::raw('SUM(enrollments_total_girls_sum) AS Total_Girls'), DB::raw('Geographies.name AS District') ) ->get();
核心逻辑说明
- 先对
enrollements按form_id分组,统计每个机构的男女总数,避免一对多join产生的重复行。 - 再将统计结果与
institutes、Geographies关联,最后按地区分组求和,得到准确的区域男女总数。
内容的提问来源于stack exchange,提问作者Sarmad Chaudhry
相关产品推荐
相关产品推荐

