Запросы для ассоциаций, которые включают все элементы - PullRequest
1 голос
/ 25 июня 2019

У меня есть 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 

Я должен написать отчет, который выбирает все счета-фактуры, имеющие InvoiceItem как item_id 1 и item_id 2

Я могу сделать это только с 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 голосов
/ 26 июня 2019

Может быть, вы могли бы попробовать использовать подзапрос здесь.Это можно сделать следующим образом: 1) Выберите invoice_items.invoice_id, где invoice_items.item_id равно 1 2) Выберите invoice_items.invoice_id, где invoice_items.item_id равно 2 3) Пересечь результат этих двух запросов, чтобы получить идентификаторы счетов, общие для обоих 4) Получать счета, используя эти идентификаторы

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, но сделает несколько подзапросов.Ваш звонок в БД из приложения будет единичным.

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