テーブル
Userテーブル -- 登録ユーザー
user_informationsテーブル -- UserテーブルとInformationテーブルの中間テーブル
payments -- Userテーブルの子要素でuser_idカラム、started_on(開始時期)とfinished_on(終了時期)カラムを持つ。
実現したいこと
以下のようなSQLで取得できるデータと同じものをrails上で取得したいと考えています。
・InformationテーブルのIDが4のレコードと紐付いている
かつ
・所有するpayemntsが全て有効期限でない(現在の日付がstarted_onとfinished_onの間にない)またはそもそもpaymentsを所有していない
という2つの条件を満たすSQLです。
SELECT * FROM users AS u INNER JOIN user_informations AS ui ON u.id = ui.user_id WHERE AND ui.information_id = 4 AND u.id NOT IN ( SELECT u.id FROM users AS u INNER JOIN payments AS p ON u.id = p.user_id WHERE AND u.deleted_at IS NULL AND p.started_on <= CURDATE() AND p.finished_on >= CURDATE() AND o.deleted_at IS NULL )
###やってみたこと
自分で考えて以下のようなコードを書いてみました。
users = User.joins(:user_informations, :payments) .where(user_informations: { information_id: 4 }) .where.not('payments.started_on <= ? AND payments.finished_on >= ?', Time.zone.today, Time.zone.today)
そして以下のようなSQLが発行されました。
User Load (463.0ms) SELECT `users`.* FROM `users` INNER JOIN `user_informations` ON `user_informations`.`user_id` = `users`.`id` INNER JOIN `payments` ON `payments`.`user_id` = `users`.`id` AND `payments'.`deleted_at` IS NULL WHERE `users`.`deleted_at` IS NULL AND `user_informations`.`informaton_id` = 4 AND (NOT (payments.started_on <= '2018-05-22' AND payments.finished_on >= '2018-05-22'))
このSQLの場合、
①userが1つでも有効期限ではないpaymentsを所有していた場合、そのuserを取得してしまう。
②userがpaymentsを一つも持っていない場合、取得されない。
という問題点があり、うまく上記の理想のSQLのようなデータ取得ができません。
問題点②は
User.joins(:user_informations).includes(:payments).where(user_informations: { informations_id: 4 }).where(payments: {id: nil})
のように別にコードを用意して、取得したuserの配列?を合体させればいいのかなと思っています。
上記の問題を解決し、理想のSQLを実現できるようにアドバイスをいただけませんでしょうか?
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。