查询包括所有项目的关联

时间:2019-06-25 15:45:55

标签: ruby-on-rails activerecord

我有3个关联:

Invoice
  has_many :invoice_items
  has_many :items, through: :invoice_items

InvoiceItem
  belongs_to :invoice
  belongs_to :item 

Item
  has_many :invoice_items
  has_many :invoices, through: :invoice_items 

我要写一个报告,选择所有同时具有item_id 1和item_id 2的InvoiceItem的发票

我可以用Ruby做到这一点。

invoices = Invoice.joins(:invoice_items).where(item_id: [1, 2])
invoices.each do |invoice|
  if ([1,2] - invoice_items.pluck(:item_id).uniq).empty?
    @real_invoices << invoice 
  end 
end 

但是对于数百万条记录,这是完全不可行的。

我尝试过:

Invoice.joins(:invoice_items).having('COUNT(CASE WHEN invoice_items.item_id IN (?) THEN 1 END) = ?',[1,2], [1,2].length).group(:id)

但这不会产生正确的结果。

1 个答案:

答案 0 :(得分:0)

也许您可以在此处尝试使用子查询。可以按照以下步骤进行: 1)选择invoice_items.invoice_id为1的invoice_items.item_id 2)在invoice_items.invoice_id为2的情况下选择invoice_items.item_id 3)将这两个查询的结果相交以获得两个都通用的发票ID 4)使用这些ID提取发票

Invoice.where("
    invoices.id IN
      (
        SELECT invoice_items.invoice_id
        FROM invoice_items
        WHERE invoice_items.item_id = 1

        INTERSECT

        SELECT invoice_items.invoice_id
        FROM invoice_items
        WHERE invoice_items.item_id = 2
      )
")

这将通过使用来自invoice_items关系的信息来防止联接,但是会进行多个子查询。但是,您从应用程序对DB的调用将是一个。