首页 > 新闻中心 > 技术百科

如何在 Laravel 中按产品名称汇总入库数量 返回列表

霞舞2026-01-15 00:00:00编辑发布,已经有个小可爱看过这篇文章啦

本文介绍如何使用 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', 'p

roducts.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); }

? 关键说明:

  • ->groupBy('products.id', 'products.name'):必须包含 products.id(主键),避免仅按 name 分组时因重名导致误合并;同时加上 name 便于 SELECT 中引用;
  • COALESCE(SUM(...), 0):将 NULL 总和(如某产品无任何入库记录)转为 0,提升数据健壮性;
  • 若希望包含无入库记录的产品(即 LEFT JOIN 场景),应改用:
    ->leftJoin('ins', 'products.id', '=', 'ins.products_id')

    并保持 GROUP BY 不变,此时 COALESCE 更为必要。

⚠️ 注意:原答案中仅加 DB::raw('sum(ins.amount) as total') 但未添加 groupBy(),在严格模式 MySQL 或 PostgreSQL 下会直接报错(如 SQLSTATE[42000]: Syntax error or access violation),因此该写法不可直接使用。

最终输出格式示例:

[
  {"name": "Aerobat", "total": 34},
  {"name": "God of war", "total": 30},
  {"name": "Rs537", "total": 15}
]

总结:聚合查询 ≠ 简单加 SUM(),务必同步声明 GROUP BY;结合 COALESCE 和 LEFT JOIN 可覆盖更完整的业务场景。

  • js
  • json
  • go
  • 数据库
  • mysql
  • postgresql
  • sql
  • access
  • Error
  • NULL

热门新闻

来电咨询