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

Laravel中如何通过Eloquent基于状态列计算各仓库的总收入

如何用Eloquent计算每个仓库的总收入(区分发货与退回)

嘿,我完全懂你的困扰——普通的withSum()确实没法直接处理这种需要根据status区分加减的统计需求,不过有几种优雅的Eloquent方案可以解决这个问题,下面给你详细说说:

方法一:使用Join + 原生SQL聚合(推荐批量查询)

这种方法通过一次数据库查询就能拿到所有仓库的总收入,性能最优,适合批量查询场景:

$warehouses = Warehouse::query()
    ->select('warehouses.*')
    // 用CASE语句分别计算发货金额和退回金额,再做差额计算
    ->selectRaw('
        COALESCE(SUM(CASE WHEN sales.status = 1 THEN sales.product_price * sales.quantity ELSE 0 END), 0) - 
        COALESCE(SUM(CASE WHEN sales.status = 2 THEN sales.product_price * sales.quantity ELSE 0 END), 0) AS total_revenue
    ')
    ->leftJoin('sales', 'warehouses.id', '=', 'sales.warehouse_id')
    ->groupBy('warehouses.id')
    ->get();

说明:

  • COALESCE用来处理没有销售记录的仓库,确保总收入显示为0而非null
  • leftJoin保证所有仓库都会被返回,哪怕没有对应的销售数据
  • 直接在数据库层面完成计算,避免PHP层面的额外处理

方法二:模型访问器(适合单个仓库查询)

如果只是查询单个仓库的总收入,可以给Warehouse模型添加一个访问器,延迟加载计算结果:

// 在Warehouse模型中添加
public function getTotalRevenueAttribute()
{
    return $this->sales()
        ->selectRaw('
            COALESCE(SUM(CASE WHEN status = 1 THEN product_price * quantity ELSE 0 END), 0) - 
            COALESCE(SUM(CASE WHEN status = 2 THEN product_price * quantity ELSE 0 END), 0) AS revenue
        ')
        ->value('revenue') ?? 0;
}

使用的时候直接访问属性即可:

$warehouse = Warehouse::find(1);
echo $warehouse->total_revenue; // 输出仓库1的总收入

注意:

  • 这种方法如果批量查询多个仓库,会触发N+1查询问题,所以批量场景不推荐

方法三:多次withSum() + PHP层面计算(直观易读)

如果你更倾向于用Eloquent的原生语法,不想写太多原生SQL,可以分两次统计发货和退回的总金额,再在PHP里做减法:

$warehouses = Warehouse::withSum(
    ['sales as shipped_total' => function ($query) {
        $query->where('status', 1)->selectRaw('product_price * quantity');
    }]
)->withSum(
    ['sales as returned_total' => function ($query) {
        $query->where('status', 2)->selectRaw('product_price * quantity');
    }]
)->get();

// 遍历计算每个仓库的总收入
foreach ($warehouses as $warehouse) {
    $totalRevenue = ($warehouse->shipped_total ?? 0) - ($warehouse->returned_total ?? 0);
    // 处理你的业务逻辑
}

说明:

  • 这种写法更贴近Eloquent的惯用方式,可读性强
  • 会执行两次子查询,性能和方法一差不多,看个人编码习惯选择

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 15:37:34