You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel Eloquent关联表按销量降序取Top5商品问题求助

Laravel Eloquent 非强制关联表按销量排序取Top5 解决方案

原代码问题梳理

  • 查询主体错误:以sell_items表为查询主体时,whereHas会过滤掉无销售记录的商品,无法得到销量为0的商品(如示例中的Xiaomi)
  • 字段引用错误:sell_items表不存在name字段,商品名称存储在items表中
  • 缺少聚合分组:sum聚合统计需要按商品维度分组,否则会返回所有销量的总和
  • 语法错误:DB::raw('sum('qty') as total')中单引号嵌套冲突,会触发语法报错
  • 逻辑顺序瑕疵:应先执行排序再取前5条数据,避免先截断数据再排序导致结果错误

正确实现代码

首先确保模型关联已正确定义:

  1. Item模型中添加sellItems关联
// App\Models\Item.php
public function sellItems()
{
    return $this->hasMany(SellItem::class, 'item_id');
}
  1. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 16:15:00