本文介绍如何使用 laravel 的 query builder 对多对一关联的库存表进行分组聚合,正确计算每个产品的入库总量,并避免因缺少 group by 导致的重复与空值问题。
在实际开发中,我们常需统计某类产品在多个入库记录中的总数量(如 Aerobat-34 表示 Aerobat 产品累计入库 34 件)。但直接 JOIN 后调用 sum() 而不配合 GROUP BY,会导致 SQL 语义错误或结果异常——正如提问者所见:原始查询返回了大量重复产品名 + 单条 amount 记录,甚至含 null 值,根本无法体现“每个产品总和”。
根本原因在于:SUM() 是聚合函数,必须配合 GROUP BY 指定分组维度(此处为产品名称),否则数据库会尝试对全表聚合,而 Laravel 默认不会自动添加 GROUP BY。
✅ 正确写法如下(Laravel 9+):
public function index()
{
$productsWithTotal = DB::table('products')
->join('ins', 'products.id', '=', 'ins.products_id')
->select('products.name', DB::raw('COALESCE(SUM(ins.amount), 0) as total'))
->groupBy('products.id', 'products.name') // 关键:按主键和名称分组,确保一致性
->get();
return response()->json($productsWithTotal);
}? 关键说明:
->leftJoin('ins', 'products.id', '=', 'ins.products_id')并保持 GROUP BY 不变,此时 COALESCE 更为必要。
⚠️ 注意:原答案中仅加 DB::raw

最终输出格式示例:
[
{"name": "Aerobat", "total": 34},
{"name": "God of war", "total": 30},
{"name": "Rs537", "total": 15}
]总结:聚合查询 ≠ 简单加 SUM(),务必同步声明 GROUP BY;结合 COALESCE 和 LEFT JOIN 可覆盖更完整的业务场景。