首页 > 解决方案 > 查找所有子记录与给定列表完全匹配的所有父母,在 Rails 中通过关联有很多

问题描述

我有以下关系

class Invoice
  has_many :entries
  has_many :price_matrixes, through: entries
end

class Entry
  belongs_to :invoice
  belongs_to :price_matrix
end

class PriceMatrix
  has_many :entries
  has_many :invoices, through: entries
end

现在,我有一组 price_matrix id,例如 [1, 2],并且我想找到只有这两个价格矩阵的所有发票。

注意:试过这个Invoice.includes(:price_matrixes).where(price_matrixes: {id: [1, 2]}),但这应该返回记录,即使列表中的一个 id 将匹配。

标签: ruby-on-railsactiverecord

解决方案


使用简单的 SQL 可以轻松解决该任务。假设您使用 PostgreSQL 9+,这是用于获取符合您的条件的发票 ID 的 SQL 查询(仅具有带有 ID [1、2] 的完全价格矩阵):

SELECT I.id
FROM invoices I  
  JOIN entries E ON E.invoice_id = I.id
GROUP BY I.id
HAVING array_agg(E.price_matrix_id ORDER BY E.price_matrix_id ASC) = ARRAY[1,2];

在这里,我们加入invoicesentries,对结果进行分组invoice.id,并只过滤那些已经给出的结果price_matrix_ids。请注意,ARRAY[1,2]表达式应包含price_matrix_ids按升序排序的内容。

在线演示:http ://rextester.com/TAEUU9220

回到 Ruby,代码如下:

price_matrix_ids = [1,2].sort

Invoice.joins(:entries).having("array_agg(entries.price_matrix_id ORDER BY entries.price_matrix_id ASC) = ARRAY[#{price_matrix_ids.join(',')}]").group('invoices.id')

推荐阅读