【Laravel】【collection】コレクションでSQLの集計クエリがしたい→ちょっとの工夫で簡単でした
こんにちは。最近LaravelのコレクションでSQLの集計をする要件がありました。その時にコレという記事が無かったのでまとめておこうと思います。
やりたいこと
group byで指定した集計単位でcount, average, sumのような集計関数を使って集計します。SQLでは頻出のパターンですね。
用意するデータ
今回はtinkerを使って検証します。まずはコレクションを用意します。部署名(busho)、名前(name), 年齢(age)の3項目を持つデータを4件登録しておきます。
=> Illuminate\Support\Collection {#4298
all: [
[
"busho" => "system1",
"name" => "sato",
"age" => 29,
],
[
"busho" => "system1",
"name" => "tanaka",
"age" => 23,
],
[
"busho" => "system2",
"name" => "ishida",
"age" => 45,
],
[
"busho" => "system2",
"name" => "tanahashi",
"age" => 25,
],
],
}
集計する
部署別の平均年齢を算出したいと思います。前述のコレクションを集計していきます。以下の2段階で説明します。
- groupByメソッドでコレクションを部署単位でまとめる
- eachで部署単位に集計関数を実行
groupByで部署単位にまとめる
まずはgroupByを実行します。groupByは部署単位に新たにコレクションを作り、それらをまとめて1つのコレクションにします。元々のデータではbushoにsystem1とsystem2の2種が登録されていました。groupByするとsystem1とsystem2のコレクションを作ります。そしてその2つのコレクションを一つのコレクションとしてまとめています。
>>> $groupByBusho = $collection->groupBy('busho');
=> Illuminate\Support\Collection {#4350
all: [
"system1" => Illuminate\Support\Collection {#4364
all: [
[
"busho" => "system1",
"name" => "sato",
"age" => 29,
],
[
"busho" => "system1",
"name" => "tanaka",
"age" => 23,
],
],
},
"system2" => Illuminate\Support\Collection {#4363
all: [
[
"busho" => "system2",
"name" => "ishida",
"age" => 45,
],
[
"busho" => "system2",
"name" => "tanahashi",
"age" => 25,
],
],
},
],
}
集計関数を部署毎に実行する
部署ごとにまとめたコレクションに対してeachメソッドを実行します。eachメソッドはforeachのようにコレクションの全件をループ処理してくれます。この場合はsystem1とsystem2の2件をループします。このループの中でsystem1と、system2の年齢に対してavgメソッド実行し平均を算出します。予め作成しておいたbushoAgeAverageというコレクションにpushしています。
>>> $bushoAgeAverage = collect();
>>> $groupByBusho->each(function($item,$key) use($bushoAgeAverage){
$bushoAgeAverage->push([
'busho' => $key,
'ageAvg' => $item->avg('age')
]);
});
こうして部署別の年齢平均のコレクションを作ることができました。
>>> $bushoAgeAverage;
=> Illuminate\Support\Collection {#4208
all: [
[
"busho" => "system1",
"ageAvg" => 26,
],
[
"busho" => "system2",
"ageAvg" => 35,
],
],
}
ディスカッション
コメント一覧
まだ、コメントがありません