You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中按service_inv_cat_id分组汇总payment金额问题

问题描述

我有两张数据表:

  1. invoice表:包含id、service_inv_cat_id等字段
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 19:18:17