2022-07-14 [Rails]to_sqlによるSQL埋め込み・fromによるサブクエリ化
RailsでいろんなSQLを発行する
下記の記事がよくまとまっていたので引用しつつ。
Rails(ActiveRecord)で自在にSQLを書く手段いろいろ | Takakisan
to_sqlによるSQL埋め込み
to_sql でSQL文字列化して joins
とか where
に埋め込むテク。
ちょっとテクニカルで読みにくくなるものの、生SQL書くよりは全然読みやすく、パフォーマンス向上のためならこれくらいは許されるかな、のレベル。
exists_sql =
Purchase.select(1)
.where('users.id = purchases.user_id')
.where(shop_id: 5)
.to_sql
users = User.where("exists (#{exists_sql})")
latest_purchases =
Purchase.where(
'not exists ('\
'select 1 from purchases sub '\
'where sub.user_id = purchases.user_id '\
'and sub.created_at > purchases.created_at'\
')'
)
users =
User.select(:id, :name, 'latest_purchases.shop_id latest_purchase_shop_id')
.joins("inner join (#{latest_purchases.to_sql}) latest_purchases "\
'on users.id = latest_purchases.user_id')
fromによるサブクエリ化
from
を使ってトリッキーにレコードfetchするとき。
with_rownum =
Purchase.select('*',
'row_number() '\
'over (partition by user_id order by created_at desc) rownum')
purchases =
Purchase.select('*')
.from(with_rownum, :with_rownum)
.where('with_rownum.rownum <= ?', 3)
公式ドキュメントだとこんな例だったりする。
Topic.select('title').from(Topic.approved)
# SELECT title FROM (SELECT * FROM topics WHERE approved = 't') subquery