2009-06-17 9 views
2

Books、Notifications、NotificationTypesの3つのモデルがあります。 Notificationモデルにはbook_idがあるため、書籍には通知があります。通知モデルが1 notification_type_idSQL noobには、ジョインを含むRailsクエリの作成に役立つ必要があります。

私は日付1とdate2の

books_set1 = Book.find :all, :conditions => ["created_at <= ? AND show_time >= ?", max_date, min_date] 

間のすべての書籍が作成したいしかし、私は考えnotification.notification_type_id = 1の通知を持って本を欲しいと理想的には私はありませんがあるよう通知は1 NOTIFICATION_TYPEを持っていますnotification.notification_type.name = 'type1'の通知を受け取った書籍は欲しくないので

既に書籍のために作成されたタイプ1の通知があった場合は、それはセットに戻ってほしいです(私はcに行くのでそのタイプの通知を返されたセットでreateします)。

1つのクエリでこれを行う方法があるかどうかわかりませんが、私は2つのクエリとINTERSECTが必要と思っています - 最初に私はこの投稿に既に含まれています。しかし、擬似コードでは、私は、これはそれを行うに必要なものだと思う:

notification_type_id = Notification.find_by_name('type1') 
get all notifications where notification_id = notification_type_id 
set2 = get the associated book set from the notification set (since each notification has one book) 

はその後、私はSET1行う - set2の

UPDATEを、私は2つのクエリを書かれているいくつかの助けに

感謝私に望ましい結果を得てください。誰もがそれを行う方法を知っている場合、私は1つのクエリであることを、このために大好きだ:

books_in_range = Book.find :all, :conditions => ["created_at <= ? AND created_at >= ?", max_date, min_date] 
books_without_these_notifications = Book.find(:all, :joins => { :notifications => :notification_type }, :conditions => ["notification_types.name = ?","type1"]) 
books_to_consider = books_in_range - books_without_these_reminders 

を繰り返しますが、アイデアはTYPE1の通知が作成されており、特定の日付範囲内に収まっていないすべての書籍を取得することです。

+1

私の答えに存在しないオプションを試しましたか?日付範囲内のすべての書籍を取得してから、すべての書籍をタイプ1の通知で取得するよりも、ほぼ確実に効率的です。 – Shadwell

+0

それは箱の外で働かない、notification_idは未定義です...しかしそれを修正し、あなたを更新し続けるでしょう。私に思い出させてくれてありがとう....私はモルフの答えにつきました – Tony

+1

私は修正するために編集しました - この関連付けは本と通知の間の間違った方法でした。 – Shadwell

答えて

2

は存在しますが、私はそれが可能だろうか効率的かわからない:

Book.find(
    :all, 
    :conditions => 
    ['created_at <= ? AND show_time >= ? AND 
     NOT EXISTS 
     (SELECT * FROM notifications 
     INNER JOIN notification_types ON notifications.notification_type_id = notification_types.id 
     WHERE notification_types.name = ? AND notifications.book_id = books.id)', 
    max_date, min_date, 'type1' 
    ]) 

あなたは別の方向からそれで来ることができるかもしれないし、それらのどのを追跡しますに書籍や書籍に直接結合された他のオブジェクトにブール値を追加することによって送出されるタイプ1の通知を持っています。あなたの質問は次のようになります:

Book.find(:all, 
    :conditions => 
    ['created_at <= ? AND show_time >= ? AND 
     type1_notification_sent = ?', 
    max_date, min_date, false 
    ]) 
+0

私はこのプロジェクトの最後までに30種類の通知のようであるかもしれない – Tony

+0

十分に公正。試すだけの価値があります! – Shadwell

0
SELECT books.* FROM books WHERE books.created_at <= ? AND books.show_time >= ? AND 
    notifications.name <> 'type1' 
LEFT OUTER JOIN notifications ON notifications.book_id = books.id AND 
    notification.name = 'type1' 

それはうまくいくと思います。

3

次は動作するはずです:

Book.scoped(:conditions => ["created_at <= ? AND show_time >= ?", max_date, 
    min_date]).find(:all, :joins => { :notifications => :notification_types }, 
    :conditions => ["notification_type.name <> ?", "type1"]) 

named_scope秒または余分明確にするためのローカル変数に引数の一部を抽出します。

否定を反映するように更新されました。そうでないと、それを行うことができ

+0

こんにちは...これを解読しようとしています。 1つの問題は、本には多くのリマインダーがないことです(理論的にはそうですが、ユーザーには一般的にアクセスする方法が多いので、多くのリマインダーがあります)。これは、通知タイプ1を持っているすべての本を返しませんか?私は通知タイプ1を持たない本で終わりたいです。 – Tony

+0

リマインダー=通知 – Tony

+0

@Tony、updated。申し訳ありませんが、私は否定を逃しました。 – molf

関連する問題