优化Laravel查询:如何用集合方法将24次查询降为1次
优化方案
完全可以通过1次查询+Laravel集合分组实现需求,你可以先批量拉取所有符合条件的销售数据做聚合,后续遍历直接从聚合结果中取值即可,完全避免循环查询。
第一步:构造单次聚合查询
我们直接筛选出产品ID在指定范围、年份在2014-2021之间的所有销售记录,按product_id和年份字段分组统计数量,全程仅执行1次SQL:
@php $products = [101 => 'product-a', 102 => 'product-b', 103 => 'product-c']; $from_year = 2014; $to_year = 2021; $productIds = array_keys($products); // 假设销售记录的年份字段为year,若需从创建时间取年份可替换为YEAR(created_at) // 如果原getSales方法有额外筛选条件(比如有效订单、已支付等),直接补充where条件即可 $salesStats = Products::whereIn('product_id', $productIds) ->whereBetween('year', [$from_year, $to_year]) ->selectRaw('product_id, year, count(*) as sales_count') ->groupBy('product_id', 'year') ->get() // 集合做二级分组,第一层key为产品ID,第二层key为年份 ->groupBy(['product_id', 'year']); @endphp
第二步:遍历直接取预统计结果,不再查库
@php foreach ($products as $product_id => $product_title) { echo "<h1>$product_title</h1>"; for ($year = $from_year; $year <= $to_year; $year++) { // 你原代码此处重复输出了产品名,大概率是笔误,调整为输出年份 echo "<h3>{$year}年销量</h3>"; // 无对应销量数据时默认返回0,和原count()返回结果完全一致 echo $salesStats->get($product_id, collect())->get($year, collect())->first()?->sales_count ?? 0; } } @endphp
优化说明
- 全程仅执行1次数据库查询,完全消除循环查询的性能损耗
- 所有结果取值都在内存中通过Laravel集合完成,运行效率远高于循环查库
- 兼容无销量的场景,返回值和原有逻辑完全一致
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

