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

Laravel Eloquent查询作用域:筛选关联表列总和大于父表字段的记录

在Laravel Eloquent中实现关联记录总和大于父表字段的查询作用域

你可以通过数据库层面的聚合过滤逻辑实现需求,避免在集合层面过滤损耗性能,以下是具体方案:

方法一:JOIN + GROUP BY + HAVING

直接关联两张表,通过聚合函数计算关联记录总和,再用havingRaw完成字段比较:

$qualifiedRecords = TableA::select('table_a.*')
    ->join('table_b', 'table_a.id', '=', 'table_b.table_a_id')
    ->groupBy('table_a.id') // 按表A主键分组,确保每条父记录只计算一次关联总和
    ->havingRaw('SUM(table_b.total) > table_a.total')
    ->get();

方法二:WHERE EXISTS子查询

如果不想使用JOIN,可通过whereExists子查询检查符合条件的关联记录组,写法更贴合Eloquent关联逻辑:

use Illuminate\Support\Facades\DB;

$qualifiedRecords = TableA::whereExists(function ($query) {
    $query->select(DB::raw('1'))
        ->from('table_b')
        ->whereColumn('table_b.table_a_id', 'table_a.id')
        ->groupBy('table_b.table_a_id')
        ->havingRaw('SUM(table_b.total) > table_a.total');
})->get();

封装为查询作用域

把逻辑封装到TableA模型的查询作用域中,方便后续复用:

// app/Models/TableA.php
use Illuminate\Support\Facades\DB;

class TableA extends Model
{
    // 定义关联(若未定义)
    public function tableBs()
    {
        return $this->hasMany(TableB::class);
    }

    // 自定义查询作用域
    public function scopeWhereRelatedTotalExceeds($query)
    {
        return $query->whereExists(function ($subQuery) {
            $subQuery->select(DB::raw('1'))
                ->from('table_b')
                ->whereColumn('table_b.table_a_id', 'table_a.id')
                ->groupBy('table_b.table_a_id')
                ->havingRaw('SUM(table_b.total) > table_a.total');
        });
    }
}

使用时直接调用作用域即可:

$qualifiedRecords = TableA::whereRelatedTotalExceeds()->get();

为什么withSum无法直接用于WHERE条件?

withSum是Eloquent在查询完成后,为集合中的模型实例添加的额外属性(比如table_b_total_sum),该属性仅存在于内存中的集合对象里,无法在数据库层面的WHERE条件中使用——我们需要的是在SQL执行阶段完成过滤,因此必须采用上述数据库端聚合方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 03:27:53