ActiveRecordでグループ中の特定のカラムに着目してレコードを選択する
3611 ワード
「男女別で最年長のユーザを選びたい」など、グループ化した際にどのレコードを選ぶのかを特定のカラムにより決めたいことが時々ある。
たとえば以下のusers
テーブルで男女ごとに最年長の人を選ぶ時、次のように書く。
id | name | age | sex |
---|---|---|---|
1 | suzuki | 20 | male |
2 | sato | 25 | male |
3 | tanaka | 35 | female |
4 | hayashi | 30 | female |
# sexカラムのグループ中で最大のageを持つレコードのidを収集する
sql = 'select id from users as m where age = (select max(age) from users as s where m.sex = s.sex);'
user_ids = User.find_by_sql(sql).map(&:id)
# User Load (0.5ms) select id from users as m where age = (select max(age) from users as s where m.sex = s.sex);
# => [2, 3]
users = User.where(id: user_ids)
# User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" IN (2, 3)
# => #<ActiveRecord::Relation [
# #<User id: 2, name: "sato", age: 25, sex: "male", created_at: "2015-05-01 10:27:54", updated_at: "2015-05-01 10:27:54">,
# #<User id: 3, name: "tanaka", age: 35, sex: "female", created_at: "2015-05-01 10:28:04", updated_at: "2015-05-01 10:28:04">
# ]>
余談
この方法を見つけるまで同じような問題に対して次のコードのようにorder
とgroup
で取り組んでいたが、この方法では上手くできない。
User.order('age desc').group(:sex)
そのため、これまではorder
でソートだけ行って同じグループのレコードを繰り返し表示しないように制御するというグダグダな方法をとっていた。
調べたところSQLによる解決方法を紹介しているページはいくつか見つかったが、ActiveRecordの例は見つからなかったのでここに書いてみた。
もっとスマートな方法を知っている人がいれば、ぜひ教えてほしい:)
参考記事
Author And Source
この問題について(ActiveRecordでグループ中の特定のカラムに着目してレコードを選択する), 我々は、より多くの情報をここで見つけました https://qiita.com/RinKeiHotman/items/6efc3981b67c58ad6638著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .