如何对MySQL/Laravel两个查询结果的数量字段做减法并保留首查询字段?
实现方案
你可以根据实际业务场景选择以下两种方案实现需求:
方案1:SQL联查实现(推荐,性能更优)
直接在数据库层面完成关联和计算,避免多次查询和PHP层面的二次处理,数据量大时性能优势非常明显:
$products = DB::table('purchase_products') ->join('products', 'products.id', '=', 'purchase_products.product_id') // 左连接销售表,关联条件为匹配product_id和purchase_price ->leftJoin('sales_products', function ($join) { $join->on('sales_products.product_id', '=', 'purchase_products.product_id') ->on('sales_products.purchase_price', '=', 'purchase_products.purchase_price'); }) ->select( 'products.product_name', 'purchase_products.product_id', 'purchase_products.purchase_price', DB::raw("SUM(purchase_products.quantity) as purchase_quantity"), // 无销售记录时默认销售数量为0,避免null导致计算错误 DB::raw("IFNULL(SUM(sales_products.quantity), 0) as sales_quantity"), // 直接计算剩余库存数量 DB::raw("SUM(purchase_products.quantity) - IFNULL(SUM(sales_products.quantity), 0) as remain_quantity") ) ->groupBy('purchase_products.product_id', 'purchase_products.purchase_price', 'products.product_name') ->get();
查询结果会保留原采购查询的所有字段,同时直接返回扣除销售后的剩余数量。
方案2:基于现有查询的集合处理
如果需要保留原有两个独立查询的逻辑,可以用Laravel集合的方法做后续匹配计算:
- 首先修改原有两个查询,补充关联必须的
product_id字段:
// 采购查询补充product_id字段 $purchase_products = DB::table('purchase_products') ->join('products','products.id','purchase_products.product_id') ->select('products.product_name','purchase_products.product_id','purchase_products.purchase_price',DB::raw("SUM(purchase_products.quantity) as purchase_quantity")) ->groupby('purchase_products.product_id','purchase_products.purchase_price', 'products.product_name') ->get(); // 销售查询补充product_id字段 $sales_products = DB::table('sales_products') ->select('sales_products.product_id','sales_products.purchase_price',DB::raw("SUM(sales_products.quantity) as sales_quantity")) ->groupby('sales_products.product_id','sales_products.purchase_price') ->get();
- 集合匹配计算剩余数量:
// 把销售集合转为键值对结构,方便快速匹配,键规则为 product_id:purchase_price $salesMap = $sales_products->keyBy(function ($item) { return $item->product_id . ':' . $item->purchase_price; }); // 遍历采购集合计算剩余数量 $result = $purchase_products->map(function ($purchase) use ($salesMap) { $key = $purchase->product_id . ':' . $purchase->purchase_price; // 无对应销售记录时销售数量默认为0 $salesQuantity = $salesMap->get($key)?->sales_quantity ?? 0; // 原采购字段全部保留,新增剩余数量字段 $purchase->remain_quantity = $purchase->purchase_quantity - $salesQuantity; return $purchase; });
最终$result即为处理后的目标数据。
内容的提问来源于stack exchange,提问作者Hola
相关产品推荐
相关产品推荐

