Laravel 集合分组求和
在 Laravel Collection 里,groupBy + sum 是一个非常常见的组合。
1. 按字段分组并求和(最常用)
示例数据
$items = collect([
['type' => 'A', 'amount' => 10],
['type' => 'A', 'amount' => 20],
['type' => 'B', 'amount' => 5],
['type' => 'B', 'amount' => 15],
]);
按 type 分组并求 amount 总和
$result = $items
->groupBy('type')
->map(fn ($group) => $group->sum('amount'));
dd($result);
结果
[
'A' => 30,
'B' => 20,
]
2. 分组后返回结构化数据
如果你想保留更多信息:
$result = $items
->groupBy('type')
->map(function ($group, $type) {
return [
'type' => $type,
'total' => $group->sum('amount'),
'count' => $group->count(),
];
})
->values(); // 可选:去掉 key
3. 多字段组合分组 + 求和
按 type + date 分组
$result = $items
->groupBy(fn ($item) => $item['type'].'_'.$item['date'])
->map(fn ($group) => $group->sum('amount'));
或者 Laravel 9+ 支持数组分组:
$result = $items
->groupBy(['type', 'date'])
->map(fn ($group) => $group->sum('amount'));
4. Eloquent 查询结果 Collection 用法
$orders = Order::whereYear('created_at', 2025)->get();
$totals = $orders
->groupBy('user_id')
->map(fn ($group) => $group->sum('price'));
5. groupBy + sum 的简写(只需要结果)
如果你只关心结果数组:
$totals = $items
->groupBy('type')
->map->sum('amount');
这是 Laravel 的 higher order messages,非常简洁 👍
6. Collection vs SQL(重要)
️ 如果数据量大,推荐在 SQL 层做 group by + sum:
Order::selectRaw('type, SUM(amount) as total')
->groupBy('type')
->pluck('total', 'type');
比 Collection 方式 更省内存、更快。
总结速查表
| 需求 | 写法 |
|---|---|
| 分组求和 | groupBy()->map->sum() |
| 返回结构化结果 | map(function(){...}) |
| 大数据量 | SQL groupBy |
| 多字段分组 | groupBy(fn(){}) 或 groupBy([...]) |
早期版本兼容写法
在 Laravel 5.2 里,Collection 的能力还比较早期,没有后来的 map->sum()、groupBy([...]) 等语法,但 groupBy + map + sum 是完全可用的。
下面是 Laravel 5.2 兼容写法
1. 基本:按字段分组并求和(Laravel 5.2)
示例数据
$items = collect([
['type' => 'A', 'amount' => 10],
['type' => 'A', 'amount' => 20],
['type' => 'B', 'amount' => 5],
['type' => 'B', 'amount' => 15],
]);
正确写法(5.2)
$result = $items->groupBy('type')->map(function ($group) {
return $group->sum('amount');
});
dd($result->all());
输出
[
'A' => 30,
'B' => 20,
]
2. 分组后返回数组结构(5.2)
$result = $items->groupBy('type')->map(function ($group, $type) {
return [
'type' => $type,
'total' => $group->sum('amount'),
'count' => $group->count(),
];
})->values(); // 可选
3. 使用回调进行分组(5.2 兼容)
$result = $items->groupBy(function ($item) {
return $item['type'];
})->map(function ($group) {
return $group->sum('amount');
});
4. Eloquent Collection(Laravel 5.2)
$orders = Order::all();
$totals = $orders->groupBy('user_id')->map(function ($group) {
return $group->sum('price');
});