スタック・オーバーフロー Asked by hatsu on September 1, 2021
Userが例えば 生まれた年(=year)
と出身の都道府県(:prefecture_id)
カラムを持っているとします。
そこから 「同じ生まれ年」かつ「同じ出身都道府県」のユーザーが3人以上いる場合、そのユーザーの一覧を取得したいです。
出力結果がHashであるため期待する結果ではないのですが、集計して多い順に並び替える処理は以下で出来ました。
User.group(:year, :prefecture_id).having("count_all > 3").order("count_all DESC").count
この出力結果は {[1990, 13]=>4, [1996,2]=>3}
のように、生まれ年と都道府県ID、一致した数になっています。
ここから、この「生まれ年」と「都道府県ID」を持つユーザーを一覧を取得するにはどのような手段がありますでしょうか?
上でのHashにUserIdがあれば、pluckとwhereを用いて取得することも出来るかと思いましたが、Idがあると適切なGroupにならないためそれも出来なかったです。。
パフォーマンスは悪いですが、以下などが一応期待した動作でした。
しかしデータ数が10万件とかなるとパフォーマンスが非常に悪いため避けたいと思っています。
user_hash = User.all.group_by{ |user| [ user[:year], user[:prefecture_id] ] }
@users = user_hash.values.select{ |user| 3 < user.size }
User.joins(<<~SQL)
INNER JOIN (
#{User.select("year, prefecture_id, count(*) as count_all").group(:year, :prefecture_id).having("count_all > ?", 3).to_sql}
) as year_pref
ON users.year = year_pref.year
AND users.prefecture_id = year_pref.prefecture_id
SQL
のようにすると、望みの User についての relation が得られるのではないか、と思っていますが、いかがでしょうか?
「該当件数」でソートしたい場合には、 sort 条件を relation に含めれば良いと思っています。 e.g.
User.joins(<<~SQL).order("year_pref.count_all DESC")
INNER JOIN (
#{User.select("year, prefecture_id, count(*) as count_all").group(:year, :prefecture_id).having("count_all > ?", 3).to_sql}
) as year_pref
ON users.year = year_pref.year
AND users.prefecture_id = year_pref.prefecture_id
SQL
Correct answer by Yuki Inoue on September 1, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP