Laravel中如何实现按商品聚合的上月订单项销量金额统计报表
实现订单项按商品聚合的两种方案
方案一:直接查询聚合(性能最优,推荐)
你可以直接从中间表order_items关联查询,按商品id分组聚合,一步拿到汇总结果,不需要遍历所有订单再处理:
use App\Models\Item; use Carbon\Carbon; // 获取上月完整时间范围,避免跨年时仅按月份查询出现数据错误 $lastMonthStart = Carbon::now()->subMonth()->startOfMonth(); $lastMonthEnd = Carbon::now()->subMonth()->endOfMonth(); $itemSummaries = Item::query() ->selectRaw('items.name, sum(order_items.quantity) as total_quantity, sum(order_items.price * order_items.quantity) as total_price') ->join('order_items', 'items.id', '=', 'order_items.item_id') ->join('orders', 'order_items.order_id', '=', 'orders.id') ->whereBetween('orders.created_at', [$lastMonthStart, $lastMonthEnd]) ->groupBy('items.id', 'items.name') ->get();
Blade 模板部分直接遍历汇总结果即可:
<table> <tr> <th>商品名称</th> <th>总数量</th> <th>总金额</th> </tr> @foreach($itemSummaries as $summary) <tr> <td>{{ $summary->name }}</td> <td>{{ $summary->total_quantity }}</td> <td>{{ $summary->total_price }}</td> </tr> @endforeach </table>
方案二:基于现有订单集合处理
如果你需要保留原有的订单查询逻辑,也可以用 Laravel 集合的方法对已有结果做聚合:
控制器部分在原有查询后补充聚合逻辑:
use Carbon\Carbon; $lastMonthStart = Carbon::now()->subMonth()->startOfMonth(); $lastMonthEnd = Carbon::now()->subMonth()->endOfMonth(); $orders = Order::with('items') ->whereBetween('created_at', [$lastMonthStart, $lastMonthEnd]) ->get(); // 按商品维度聚合数据 $itemSummaries = collect(); $orders->pluck('items')->flatten()->each(function ($item) use ($itemSummaries) { if ($itemSummaries->has($item->id)) { $existItem = $itemSummaries->get($item->id); $existItem['total_quantity'] += $item->pivot->quantity; $existItem['total_price'] += $item->pivot->price * $item->pivot->quantity; $itemSummaries->put($item->id, $existItem); } else { $itemSummaries->put($item->id, [ 'name' => $item->name, 'total_quantity' => $item->pivot->quantity, 'total_price' => $item->pivot->price * $item->pivot->quantity ]); } });
Blade 遍历逻辑和方案一完全一致即可。
注意:原查询仅用
whereMonth筛选月份会出现跨年数据错误问题,比如今年1月查询上月会拿到往年所有12月的订单,建议替换为whereBetween限定完整的上月时间范围。
内容的提问来源于stack exchange,提问作者Prince
相关产品推荐
相关产品推荐

