こんにちは。webなみ屋の宮崎です。
今回は似ているけど全く別物の group_by
(Ruby)と group
(Rails)です。SQLに GROUP BY
という構文があるため紛らわしいのですが、両方は全く別物なのでそれぞれの特徴と違いをご紹介します。
group_by
group_by
はRubyのEnumerableクラスのメソッドです。Enumerableクラスは配列などの繰り返し処理が可能なクラスにインクルードされているモジュールで、対象のany?やselectなどのデータの存在確認や絞り込みなどを行えるメソッドがあります。
group_by
メソッドは渡されたブロック内の処理を実行した結果を、キーと値(配列)のハッシュとして返します。以下は1 ~ 10の数値を任意の数で割った時の余りをキーとし、その余りになる数値を値の配列としています。
(1..10).group_by {|i| i % 2}
=> {1=>[1, 3, 5, 7, 9], 0=>[2, 4, 6, 8, 10]}
(1..10).group_by {|i| i % 3}
=> {1=>[1, 4, 7, 10], 2=>[2, 5, 8], 0=>[3, 6, 9]}
この特徴を使えば、特定のカラムで絞り込んだレコードを取得することができます。Railsのgroupメソッドは「グループ分けした結果、グループそれぞれにレコードがいくつあったか?」という様な使い方をするため、ActiveRecordのデータ自体を取得するには、その結果を元にさらにwhereなどで絞り込む必要があります。しかし group_by
メソッドはより単純に、グループ分けされたレコード自体を取得することができます。
User.all.group_by(&:age)
=> {"10"=>[<#User:0x000....>,<#User...>],"20"=>[<#User:...>...]}
ただしこちらはあくまでもRubyのメソッドで、配列などの繰り返し処理が可能なオブジェクトに対するものであり、データベースに特化したものではありません。
group
group
はRailsのActive Recordのメソッドで、MySQLなどのGROUP BYはこちらに当たります。
group
メソッドは通常単体では使用せず、countなどの集計メソッドと併用することで使用できます。イメージとしてはgroupメソッドでまとめて、countでその合計値を求めるという様な感じです。以下の例では年齢層でグループ分けして、各グループでレコードがいくつあるかを集計しています。
User.group(:age_group).count
=> {10=>50,20=>160,30=>130}
この特徴を活用すると集計をするのにとても役に立ちます。以下のように商品テーブルと、売れた分を記録する商品ステータステーブルがあるとします。
items | |
---|---|
name | 商品名 |
price | 販売価格 |
sale_informations | |
---|---|
item_id | itemのid |
total_sales | 販売数 |
total_price | 販売合計額 |
Item別で総販売数を出したい場合は、 group
でグループ化した後で、 sum
を使って合計値を出すことができます。
SaleInformation.group(:item_id).sum(:total_sales)
=>{
1=>104,
2=>152,
3=>68,
...
}
group
メソッドは単体で使用することはなく、 count
や sum
の様に集計系のメソッドと併用して使用します。ですのでグループでまとめて、各グループ内のレコード情報を一つずつ使用したい場合には工夫が必要になります。(個人的にその様な場合はRuybの group_by
を使用する方が手っ取り早い気がしています…)
まとめ
いかがでしたでしょうか?名前が似ているため混同しやすい二つのメソッドですが、それぞれ全く別物で使用目的も異なっています。今回記事を書くに当たってこちらの記事で勉強させていただきました。どちらもより詳しい解説が書かれています。
group_by
group
コメント