SQL noob нужна помощь в написании запроса Rails, включающего соединения и, возможно, пересечение - PullRequest
2 голосов
/ 18 июня 2009

У меня есть 3 модели: Книги, Уведомления и Типы уведомлений. Книги имеют уведомления, так как модель уведомлений имеет book_id. У уведомлений есть один тип уведомления, так как в модели уведомлений есть один идентификатор_идентификации_100 *

Я хочу, чтобы все книги были созданы между датой 1 и датой 2

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

Но я не хочу, чтобы в книгах были уведомления о Notification.notification_type_id = 1, и в идеале я хотел бы сказать это, ссылаясь на Notification_type.name, поэтому я не хотел бы, чтобы книги, которые имеют уведомления Notification.notification_type.name = 'type1 «

Если для книги уже создано уведомление типа 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

Благодаря некоторой помощи я написал два запроса, которые дают мне желаемые результаты. Я хотел бы, чтобы это было в 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

Опять же, идея состоит в том, чтобы получить все книги, которые не имеют уведомления о типе 1, созданы и попадают в определенный диапазон дат.

Ответы [ 3 ]

3 голосов
/ 18 июня 2009

Должно работать следующее:

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 s или локальные переменные для большей ясности.

Обновлено с учетом отрицания.

2 голосов
/ 18 июня 2009

Вы можете сделать это с NOT EXISTS, но я не уверен, насколько эффективно это будет:

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 голосов
/ 18 июня 2009
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'

Это бы сработало, я бы подумал.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...