Laravel 8 三表join查询获取关联表max(price)与max(stock)失败如何解决
问题原因
- 你代码中使用了
MAX()聚合函数,但缺少GROUP BY子句,Laravel 8默认开启MySQL严格模式,这类不符合SQL规范的查询会直接报错无法执行 - 直接同时关联
details和detail_colors两个表会产生笛卡尔积,当单个产品对应多条明细、多条颜色库存记录时,聚合计算的结果也会出现偏差
修复方案
方案1:补充分组条件(适合简单场景)
在原有查询基础上添加groupBy子句,将产品表主键作为分组条件即可:
$products = Product:: join('details', function (JoinClause $join) { $join->on('products.id', '=', 'details.product_id'); }) ->join('detail_colors', function (JoinClause $join) { $join->on('products.id', '=', 'detail_colors.product_id'); }) ->select('products.*', DB::raw('max(details.price) as price'), DB::raw('max(detail_colors.stock) as stock')) ->groupBy('products.id') ->get();
注意:如果你的MySQL严格模式要求所有非聚合字段都放入group by,需要把select里用到的products表字段全部加到groupBy参数中
方案2:子查询实现(推荐,结果更准确)
用子查询单独计算每个产品的最高价格和最高库存,避免笛卡尔积导致的结果异常:
$products = Product::query() ->select('products.*') ->selectSub(function ($query) { $query->from('details') ->whereColumn('details.product_id', 'products.id') ->selectRaw('MAX(price)'); }, 'price') ->selectSub(function ($query) { $query->from('detail_colors') ->whereColumn('detail_colors.product_id', 'products.id') ->selectRaw('MAX(stock)'); }, 'stock') ->get();
方案3:关联聚合(最简洁,适合已定义模型关联的场景)
如果已经在Product模型中定义了和details、detail_colors的关联关系,可以直接用Laravel提供的关联聚合方法,代码更简洁易读:
// 前提:Product模型中已定义details()、detailColors()关联方法 $products = Product::query() ->withMax('details as price', 'price') ->withMax('detailColors as stock', 'stock') ->get();
内容的提问来源于stack exchange,提问作者farsheed ahmadian
相关产品推荐
相关产品推荐

