Laravel Eloquent关联表按销量降序取Top5商品问题求助
Laravel Eloquent 非强制关联表按销量排序取Top5 解决方案
原代码问题梳理
- 查询主体错误:以
sell_items表为查询主体时,whereHas会过滤掉无销售记录的商品,无法得到销量为0的商品(如示例中的Xiaomi) - 字段引用错误:
sell_items表不存在name字段,商品名称存储在items表中 - 缺少聚合分组:sum聚合统计需要按商品维度分组,否则会返回所有销量的总和
- 语法错误:
DB::raw('sum('qty') as total')中单引号嵌套冲突,会触发语法报错 - 逻辑顺序瑕疵:应先执行排序再取前5条数据,避免先截断数据再排序导致结果错误
正确实现代码
首先确保模型关联已正确定义:
Item模型中添加sellItems关联
// App\Models\Item.php public function sellItems() { return $this->hasMany(SellItem::class, 'item_id'); }
SellItem模型中添加sell关联
// App\Models\SellItem.php public function sell() { return $this->belongsTo(Sell::class, 'sell_id'); }
查询代码(适配Laravel 8及以上版本):
$thisYear = date('Y'); $topProducts = Item::select('id', 'name') ->withSum([ 'sellItems as total_qty' => function ($query) use ($thisYear) { // 限定只统计今年的销售记录 $query->whereHas('sell', function ($q) use ($thisYear) { $q->whereYear('created_at', $thisYear); }); } ], 'qty') // 销量为null的商品排在最后,统一转0 ->orderByRaw('IFNULL(total_qty, 0) DESC') ->take(5) ->get() // 把null销量转换为0 ->map(function ($item) { $item->total_qty = $item->total_qty ?? 0; return $item; });
输出适配
如果需要生成带有序号的表格,可直接遍历集合,序号为当前索引+1即可:
// 示例输出处理 $output = $topProducts->values()->map(function ($item, $index) { return [ 'No' => $index + 1, 'Product' => $item->name, 'Total (Qty)' => $item->total_qty ]; });
得到的$output数组即可直接渲染为你需要的表格结构,和预期输出完全一致。
内容的提问来源于stack exchange,提问作者Elly Murgadon
相关产品推荐
相关产品推荐

