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

如何用Eloquent优化商品维度聚合查询?将6次慢查询合并为单次

问题

我有一个类似$products = Product::query()->where(...)...的查询,需要为双范围滑块获取商品的尺寸极值,当前写法如下:

$dimensionLimits = [
    'width' => [
        'min' => $products->min('width'),
        'max' => $products->max('width')
    ],
    'height' => [
        'min' => $products->min('height'),
        'max' => $products->max('height')
    ],
    'depth' => [
        'min' => $products->min('depth'),
        'max' => $products->max('depth')
    ],
];

该写法会产生6次相对较慢的查询,我想知道能否不使用原生SQL,而是用Eloquent生成的查询将其优化为单次查询?

优化方案

当然可以用Eloquent的聚合查询一次性搞定,只需要一次数据库请求就能获取所有维度的极值,不用跑6次查询。给你两种实现方式:

方法一:用selectRaw快速实现

这种写法最简洁,直接在查询里指定要计算的所有聚合值:

$stats = $products->selectRaw(
    'MIN(width) as width_min, MAX(width) as width_max, 
     MIN(height) as height_min, MAX(height) as height_max, 
     MIN(depth) as depth_min, MAX(depth) as depth_max'
)->first();

$dimensionLimits = [
    'width' => [
        'min' => $stats->width_min,
        'max' => $stats->width_max
    ],
    'height' => [
        'min' => $stats->height_min,
        'max' => $stats->height_max
    ],
    'depth' => [
        'min' => $stats->depth_min,
        'max' => $stats->depth_max
    ],
];

方法二:纯Eloquent链式调用(无原生SQL片段)

如果不想写原生SQL的字段部分,可以用addSelect配合子查询的方式实现:

$stats = $products->addSelect([
    'width_min' => Product::query()->selectRaw('MIN(width)')->whereColumn('products.id', 'products.id'),
    'width_max' => Product::query()->selectRaw('MAX(width)')->whereColumn('products.id', 'products.id'),
    'height_min' => Product::query()->selectRaw('MIN(height)')->whereColumn('products.id', 'products.id'),
    'height_max' => Product::query()->selectRaw('MAX(height)')->whereColumn('products.id', 'products.id'),
    'depth_min' => Product::query()->selectRaw('MIN(depth)')->whereColumn('products.id', 'products.id'),
    'depth_max' => Product::query()->selectRaw('MAX(depth)')->whereColumn('products.id', 'products.id'),
])->first();

// 整理成需要的数组结构
$dimensionLimits = [
    'width' => [
        'min' => $stats->width_min,
        'max' => $stats->width_max
    ],
    'height' => [
        'min' => $stats->height_min,
        'max' => $stats->height_max
    ],
    'depth' => [
        'min' => $stats->depth_min,
        'max' => $stats->depth_max
    ],
];

两种方法都能实现单次查询,第一种效率更高、代码更短,推荐优先使用。另外要注意,你之前构建的$products查询实例里的where条件会被自动继承,聚合计算只会针对过滤后的商品数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 08:50:07