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

Laravel/PHP取Top9合并剩余项为Other的高效实现方案

优化实现方案

完全可以把核心聚合逻辑下推到数据库层完成,大幅减少PHP和数据库之间的数据传输量、PHP内存占用,SKU量级越大性能提升越明显。


方案1:数据库层直接输出最终结果(推荐,适用于MySQL 8.0+、PostgreSQL、SQLite 3.25+等支持窗口函数的数据库)

核心逻辑是先用窗口函数按金额降序给每个聚合后的SKU打上排名,排名前9的保留原SKU,排名9之后的统一归为Other分组求和,最终数据库直接返回10条结果,不需要PHP做二次数组加工。
Laravel查询构造器实现代码如下:

// 拼接和原逻辑一致的金额计算表达式
$amountExpr = DB::raw('SUM(analytics.price' . ($costs ? ' + ' . $costs : '') . ') as amount');

// 第一步:先按SKU聚合金额,和你原逻辑的基础查询一致
$skuAggSubquery = DB::table('analytics')
    ->whereBetween('order_date', [$start, $end])
    ->whereIn('source', $suppliers)
    ->groupBy('sku')
    ->select('sku', $amountExpr);

// 第二步:打排名、分组合并Other、排序
$finalResult = DB::query()
    ->fromSub(function ($query) use ($skuAggSubquery) {
        $query->fromSub($skuAggSubquery, 'sku_agg')
            ->selectRaw('sku, amount, ROW_NUMBER() OVER (ORDER BY amount DESC) as rank');
    }, 'ranked_sales')
    ->selectRaw("
        CASE WHEN rank <= 9 THEN sku ELSE 'Other' END as sku,
        SUM(amount) as amount
    ")
    ->groupBy(DB::raw("CASE WHEN rank <= 9 THEN sku ELSE 'Other' END"))
    // 保证Other固定在最后一位,前9条保持金额降序
    ->orderByRaw("CASE WHEN sku = 'Other' THEN 2 ELSE 1 END, amount DESC")
    ->get();

如果你用的是不支持窗口函数的老版本数据库(比如MySQL 5.7),不推荐硬写复杂SQL实现这个逻辑,可维护性太差,直接优化PHP层处理逻辑即可,性能损失可以忽略。


方案2:PHP层逻辑精简(兼容所有数据库版本)

你当前的实现逻辑本身没有功能性问题,只是有冗余的数组转换、手动求和操作,可以直接用Laravel集合的内置方法简化,代码更简洁,性能也略有提升:

$skuAgg = DB::table('analytics')
    ->whereBetween('order_date', [$start, $end])
    ->whereIn('source', $suppliers)
    ->select([
        'sku',
        DB::raw('SUM(analytics.price' . ($costs ? ' + ' . $costs : '') . ') as amount'),
    ])
    ->orderBy('amount', 'DESC')
    ->groupBy('sku')
    ->get();

// 直接取前9条
$result = $skuAgg->take(9);
// 直接对剩余条目求和,不需要手动转数组、写reduce
$otherTotal = $skuAgg->skip(9)->sum('amount');

if ($otherTotal > 0) {
    $result->push((object)[
        'sku' => 'Other',
        'amount' => $otherTotal
    ]);
}

注意:你贴的原代码里查询时金额别名是amount,后面求和时取的是cogs字段,属于笔误,实际使用时记得统一字段名,避免报错。


内容的提问来源于stack exchange,提问作者Riza Khan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 04:31:11