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

Laravel Query Builder:如何对withSum()生成的字段进行计算?

解决Laravel中自关联模型父产品与子产品数量差值的计算问题

问题原因

你之前的写法无效,是因为withSum是Eloquent的关联预加载方法,它会单独执行查询计算子产品的数量总和,再把结果附加到模型实例上——这个别名ttl_children不是主查询的字段,所以无法在addSelect中直接引用。

解决方案

方案1:数据库层面直接计算(子查询方式)

通过子查询在主SQL中直接计算子产品总和与差值,适合大数据量场景:

use Illuminate\Support\Facades\DB;

$products = Product::query()
    ->select([
        '*', // 加载产品原有字段
        // 计算子产品数量总和
        DB::raw('(SELECT SUM(qty) FROM products WHERE parent_id = products.id) as sum_children'),
        // 计算剩余数量,用COALESCE处理无子女的情况(避免null值)
        DB::raw('qty - COALESCE((SELECT SUM(qty) FROM products WHERE parent_id = products.id), 0) as remaining')
    ])
    ->whereNull('parent_id') // 可选:只查询父产品,根据需求调整
    ->get();

方案2:集合层面处理(简洁易用)

先用withSum预加载子产品总和,再通过集合的map方法计算差值,代码更简洁,适合小数据量场景:

$products = Product::withSum('children as sum_children', 'qty')
    ->get()
    ->map(function ($product) {
        // 处理无子女的情况,默认总和为0
        $product->remaining = $product->qty - ($product->sum_children ?? 0);
        return $product;
    });

方案3:关联Join+分组计算

通过自关联Join结合分组来计算总和与差值:

use Illuminate\Support\Facades\DB;

$products = Product::query()
    ->leftJoin('products as children', 'products.id', '=', 'children.parent_id')
    ->select([
        'products.*',
        DB::raw('SUM(children.qty) as sum_children'),
        DB::raw('products.qty - COALESCE(SUM(children.qty), 0) as remaining')
    ])
    ->groupBy('products.id') // 按父产品分组
    ->get();

验证结果

以上三种方法都能得到你期望的结果:每个父产品模型会包含sum_children(子产品数量总和)和remaining(父产品数量减去子产品总和的差值)字段。

内容的提问来源于stack exchange,提问作者Hùng Thái

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 20:55:01