代码之家  ›  专栏  ›  技术社区  ›  Tony

SQL Noob需要帮助编写一个涉及连接或交叉的Rails查询

  •  2
  • Tony  · 技术社区  · 16 年前

    我有3个模型:书籍、通知和通知类型。由于通知模型具有书籍ID,因此书籍具有通知。通知具有一个通知类型,因为通知模型具有一个通知类型ID。

    我要在日期1和日期2之间创建所有书籍

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

    但我不想要有通知的书。通知类型为“id=1”,理想情况下,我想通过引用通知类型为“name”来说明这一点,这样我就不想要有通知通知类型为“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

    更新

    多亏了一些帮助,我写了两个查询来获得所需的结果。如果有人知道怎么做的话,我希望这是一个问题:

    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 回复  |  直到 16 年前
        1
  •  2
  •   Shadwell    16 年前

    你可以在不存在的情况下做,但我不确定它有多有效:

    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'
        ])
    

    你也许可以从不同的方向来跟踪那些 通过向Books或其他直接与Books联接的对象添加布尔值来发送type1通知。那么您的查询可能是:

    Book.find(:all, 
      :conditions => 
        ['created_at <= ? AND show_time >= ? AND 
          type1_notification_sent = ?', 
         max_date, min_date, false
        ])
    
        2
  •  3
  •   molf    16 年前

    以下内容应该有效:

    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或局部变量,以提高清晰度。

    更新以反映否定。

        3
  •  0
  •   Ben Hughes    16 年前
    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'
    

    我可以想象,这是可行的。