Laravel中按service_inv_cat_id分组汇总payment金额问题
问题描述
我有两张数据表:
- invoice表:包含id、service_inv_cat_id等字段
- payment表:包含id、invoice_id、amount等字段
需求是按service_inv_cat_id分组,汇总payment表中对应记录的amount字段总和。但在现有代码中添加->groupBy('service_inv_cat_id')后,仅返回单条记录的金额汇总,无法获取分组后的各分类总金额,请求解决。
现有代码如下:
$income_details_cat = Invoice::select('id', 'service_inv_cat_id') ->with(['service_inv_cat' => function ($q) { $q->select('id', 'name');}]) ->with(['payment' => function ($q) use ($year, $month){ $q->select('id','invoice_id', 'amount') ->whereYear('paid_date', $year) ->whereMonth('paid_date', $month) ;}]) ->whereHas('payment', function ($q) use ($year,$month) { return $q->where('type', 3) ->whereYear('paid_date', $year) ->whereMonth('paid_date', $month) ;}) ->withSum(['payment' => function ($query) use ($year, $month){ $query->whereYear('paid_date', $year) ->whereMonth('paid_date', $month); }], 'amount') ->get();
解决方案
你当前的问题核心是select里的invoice.id干扰了分组逻辑(每个invoice的id唯一,分组后会按id拆分结果),同时聚合逻辑没有和分组正确匹配。以下是两种可行的修改方案:
方案1:直接关联表做分组聚合(高效简洁)
$income_details_cat = Invoice::select( 'service_inv_cat_id', \DB::raw('SUM(payment.amount) as total_amount') ) ->join('payment', 'invoice.id', '=', 'payment.invoice_id') ->where('payment.type', 3) ->whereYear('payment.paid_date', $year) ->whereMonth('payment.paid_date', $month) ->groupBy('service_inv_cat_id') ->with(['service_inv_cat' => function ($q) { $q->select('id', 'name'); }]) ->get();
方案2:保留withSum写法(适合需保留其他关联场景)
$income_details_cat = Invoice::select('service_inv_cat_id') ->whereHas('payment', function ($q) use ($year,$month) { $q->where('type', 3) ->whereYear('paid_date', $year) ->whereMonth('paid_date', $month); }) ->withSum(['payment' => function ($query) use ($year, $month){ // 必须加入type=3的条件,避免统计不符合要求的记录 $query->where('type', 3) ->whereYear('paid_date', $year) ->whereMonth('paid_date', $month); }], 'amount') ->with(['service_inv_cat' => function ($q) { $q->select('id', 'name'); }]) ->groupBy('service_inv_cat_id') ->get();
关键说明
- 必须移除
select中的invoice.id,否则数据库会将每个不同的id视为独立分组,导致结果不符合预期。 - 聚合查询时要把payment的所有过滤条件(type、日期)都加上,确保只统计符合要求的金额。
内容的提问来源于stack exchange,提问作者Shady Hesham
相关产品推荐
相关产品推荐

