Laravel 计算具有条件的两列之和

Laravel calculate sum of two columns with a condition

我有从数据库中获取的这个仓库集合

[
    {
        "id": 1,
        "warehouse": "India"
        "sales": [
            {
                "id": 1,
                "warehouse_id": 1,
                "price": "120.00",
                "quantity": 1000,
                "status": 1
            },
            {
                "id": 2,
                "warehouse_id": 1,
                "price": "20.00",
                "quantity": 100,
                "status": 1
            },
            {
                "id": 3,
                "warehouse_id": 1,
                "price": "40.00",
                "quantity": 1000,
                "status": 2
            }
        ]
    },
    {
        "id": 2,
        "warehouse": "Malaysia"
        "sales": [
            {
                "id": 4,
                "warehouse_id": 2,
                "price": "160.00",
                "quantity": 100,
                "status": 1
            }
        ]
    }
]

我要计算每个仓库的总收入

总收入是根据销售status属性计算的

如果状态 = 1,则产品已交付,因此应将 price * quantity 添加到总收入中

如果 status = 2,产品被退回,所以它应该从总收入中减去 price * quantity

印度仓库的基本示例:

total_income = 120*1000 + 20*100 - 40*1000

马来西亚:

total_income = 160*100

我试过使用 Warehouse::withSum();,但没有任何效果。 我想知道是否有处理集合的好方法

老实说,我会走下面的路线:

显然,如果您不使用完整的数字(如您的示例),我的解决方案将不得不稍作修改。 if/else 也可以扩大,如果你有超过 2 个状态。

$total_income = 0;

foreach($warehouses as $warehouse)
{
    foreach($warehouse->sales as $sale)
    {
        if($sale->status = 1)
        {
            $total_income += ($sale->price * $sale->quantity);
        }else{
            $total_income -= ($sale->price * $sale->quantity); 
        }
    }
}

这是我将如何做的粗略示例。似乎每个 'warehouse' 都有不同的位置。印度对马来西亚。我的示例更多地是关于总计,但您始终可以将每个不同仓库的结果保存在不同的变量中,或者作为数组中的 key/value 对(我会这样做)。

您可以将一些回调传递给集合的 sum() 方法:

$warehouses_collection->map(function ($warehouse) {
    return (object) [
        'id' => $warehouse->id,
        'warehouse' => $warehouse->warehouse,
        'total_income' => collect($warehouse->sales)->sum(function ($sale) {
            ((int) $sale->price) * $sale->quantity * ($sale->status == 1 ? 1 : -1)
        })
    ];
});

WithSum 在这里使用有点棘手,但调用 withAggregate 可以。

Warehouse::withAggregate(
    'sales as total_income',
    'sum(case when status = 1 then price * quantity when status = 2 then price * quantity * -1 else 0 end)'
)->get()