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

Laravel Eloquent实现关联查询并按类型统计金额求和

解决Laravel Eloquent关联统计各类型金额总和的问题

Hey Andrew, 我来帮你搞定这个问题!你需要的是获取每个项目的全部字段,同时按发票类型分别统计金额总和,这可以通过条件聚合函数或者Laravel Eloquent自带的关联聚合方法来实现,下面给你两种可行的方案:

方案1:使用Query Builder的Join + 条件聚合

这种方式直接通过数据库查询构造器实现,适合不需要模型关联的场景:

$projects = DB::table('projects')
    ->leftJoin('invoices', 'projects.id', '=', 'invoices.proj_id')
    ->select([
        'projects.*',
        // 统计type为a的金额总和,别名a
        DB::raw('SUM(CASE WHEN invoices.type = "a" THEN invoices.amount ELSE 0 END) AS a'),
        // 统计type为b的金额总和,别名b
        DB::raw('SUM(CASE WHEN invoices.type = "b" THEN invoices.amount ELSE 0 END) AS b'),
        // 统计type为c的金额总和,别名c
        DB::raw('SUM(CASE WHEN invoices.type = "c" THEN invoices.amount ELSE 0 END) AS c')
    ])
    ->groupBy('projects.id') // 按项目ID分组,确保每个项目只返回一条记录
    ->get();

关键点说明:

  • leftJoin保证即使某个项目没有对应类型的发票,也会返回该项目的记录,对应类型的金额会显示0(如果去掉ELSE 0则会显示null)
  • CASE WHEN是条件聚合的核心,只对匹配类型的发票金额求和
  • 如果你的MySQL开启了严格模式,需要把projects表的所有字段都加到groupBy里,或者修改数据库配置中的sql_mode(不推荐),不过由于projects.id是主键,大部分MySQL版本会允许只按主键分组

方案2:使用Eloquent模型关联聚合(推荐)

如果你已经定义了Project和Invoice模型,并且建立了关联关系,这种方式更符合Laravel的最佳实践:

首先确保模型关联正确:

// app/Models/Project.php
class Project extends Model
{
    public function invoices()
    {
        return $this->hasMany(Invoice::class, 'proj_id');
    }
}

// app/Models/Invoice.php
class Invoice extends Model
{
    public function project()
    {
        return $this->belongsTo(Project::class, 'proj_id');
    }
}

然后使用withSum方法分别统计各类型的金额:

$projects = Project::query()
    // 统计type为a的发票金额总和,别名a
    ->withSum(['invoices as a' => function ($query) {
        $query->where('type', 'a');
    }], 'amount')
    // 统计type为b的发票金额总和,别名b
    ->withSum(['invoices as b' => function ($query) {
        $query->where('type', 'b');
    }], 'amount')
    // 统计type为c的发票金额总和,别名c
    ->withSum(['invoices as c' => function ($query) {
        $query->where('type', 'c');
    }], 'amount')
    ->get();

关键点说明:

  • withSum是Laravel提供的关联聚合方法,自动处理关联查询和聚合逻辑
  • 通过闭包过滤发票类型,并给每个聚合结果指定别名(as a),最终结果中会直接出现a、b、c三个字段
  • 这种方式不需要手动写groupBy,Laravel会自动处理,代码更简洁易维护

两种方案最终都会得到你期望的结果:每个项目一行数据,包含项目全部字段和各类型发票的金额总和。

内容的提问来源于stack exchange,提问作者Andrew Good

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:46:54