こんにちは!kossyです!
さて、今回はActiveRecordのpluckではなくselectを使ってサブクエリを書いて、
一回のSQL発行でデータを取得する方法について、ブログに残してみたいと思います。
環境
Ruby 2.5.1
Rails 6.0.3.2
MacOS Catalina
サブクエリとは
「副問合せ」ともいい、SQL文の中に入れ子になって書かれたSQL文のことです。
サブクエリを用いることで、複雑な問合せが可能になったり、書き方によっては
余計なSQLの発行を防ぐことができます。
前提
・Userモデル(ユーザー)
・DailyReportモデル(日記)
user has_many daily_reports
daily_report belongs_to user
という関連が組まれていると想定
実験
pluckの場合
(条件が残念なのは勘弁してください、、、)
「日記テーブルの中で紐づくユーザーが昨日よりも最近作られたユーザーの日記を取得したい」という場合
pluckだとSQLが2回発行される
$ DailyReport.where(user_id: User.where('created_at > ?', Date.yesterday).pluck(:id)) (0.6ms) SELECT `users`.`id` FROM `users` WHERE (created_at > '2020-11-26') # 1回目 DailyReport Load (0.7ms) SELECT `daily_reports`.* FROM `daily_reports` WHERE `daily_reports`.`user_id` IN (9, 10, 11, 12) # 2回目
Selectの場合
1回の発行で取得できる
$ DailyReport.where(user_id: User.where('created_at > ?', Date.yesterday).select(:id)) DailyReport Load (3.4ms) SELECT `daily_reports`.* FROM `daily_reports` WHERE `daily_reports`.`user_id` IN (SELECT `users`.`id` FROM `users` WHERE (created_at > '2020-11-26'))
IN区の中でSELECT文を使って、1回のSQL発行で問合せを行っているのがわかります。
サブクエリを使って、パフォーマンスのいいアプリケーションを作りましょう!
勉強になりました。
参考にさせていただいたサイト
https://madogiwa0124.hatenablog.com/entry/2018/11/30/183412