【rails】これは便利!「.find_by_sql()」でも「?」が使えてびびった話
railsを使いながらmysqlのデータを取得する機会というのはwebサービスで必要で、
単一のテーブルや単純な条件であれば「.where()」を使い、
指定の条件であればモジュールに引数にオブジェクトを渡し、
「?」を使用してその値を利用したりするかと思います。
しかし、複数テーブルの利用や複雑なSQL(JOINなど)の場合、「.where()」だとパフォーマスが下がる場合は「.find_by_sql()」を利用します。
その「.find_by_sql()」でも「.where()」同様、「?」が利用できるようになりました。
例えば
.where()の場合
/where("reserv.reserv_date BETWEEN ? AND ?", date.to_date.beginning_of_month, date.to_date.end_of_month)
.find_by_sql()の場合
.find_by_sql (["select c.* from campaigns c
join (
select r1.user_id from enquetes e1
join reservs r1 on e1.reservs_id = r1.id
where e1.created_at between ? and ? and
not exists (
select 1 from enquetes e2
join reservs r2 on e2.reservs_id = r2.id
where r1.user_id = r2.user_id and e2.created_at < e1.created_at
)
) e on c.user_id = e.user_id
where c.campaigns_id = 2",base_date.beginning_of_month,base_date.end_of_month])
join (
select r1.user_id from enquetes e1
join reservs r1 on e1.reservs_id = r1.id
where e1.created_at between ? and ? and
not exists (
select 1 from enquetes e2
join reservs r2 on e2.reservs_id = r2.id
where r1.user_id = r2.user_id and e2.created_at < e1.created_at
)
) e on c.user_id = e.user_id
where c.campaigns_id = 2",base_date.beginning_of_month,base_date.end_of_month])
となります。
ポイントは[]と""の範囲なので、そのあたりを覚えて頂けたらすぐに使えると思います。
改めてこのような複雑なSQLを書く場合や、.where()だと不要なデータの抽出や処理が発生する場合があることが分かる場合、覚えていて損はないです。