Rails找到具有两个具有特定属性的子项的Parent

我的数据库中有超过100,000个对象用于不同的产品。 每个产品有4-6个变体。 因此,通过遍历所有内容来懒惰地编辑大量数据并不容易。 因此,我试图只获得我需要的确切数量的产品。

到目前为止,我可以获得所有具有尺寸属性为“SM”的Variant的产品。

挂起的是,所有产品都具有尺寸为“MD”和“SM”的Variant。

这是我使用的代码Product.joins(:variants).where('variants.size = ?', 'SM')

我尝试过添加.where('variants.size = ?', 'MD') ,但确实有效。

这个怎么样

 Product.where( id: Variant.select(:product_id) .where(size: 'SM') ).where(id: Variant.select(:product_id) .where(size: 'MD') ) 

这应该产生类似于的东西

 SELECT products.* FROM products WHERE products.id IN (SELECT variants.product_id FROM variants WHERE size = 'SM') AND products.id IN (SELECT variants.product_id FROM variants WHERE size = 'MD') 

所以产品ID必须在两个列表中才能被选中。

此外,这也应该工作(不是100%确定)

 Product.where(id: Product.joins(:variants) .where(variants: {size: ['SM', 'MD']}) .group(:id) .having('COUNT(*) = 2').select(:id) 

哪个应该生成类似的东西

 SELECT products.* FROM products WHERE products.id IN ( SELECT products.id FROM products INNER JOIN variants ON variants.product_id = products.id WHERE variants.size IN ('SM','MD') GROUP BY products.id HAVING Count(*) = 2 

还有一个选择

 p_table = Products.arel_table v_table = Variant.arel_table sm_table = p_table.join(v_table) .on(v_table[:product_id].eq(p_table.[:id]) .and(v_table[:size].eq('SM')) ) md_table = p_table.join(v_table) .on(v_table[:product_id].eq(p_table.[:id]) .and(v_table[:size].eq('MD')) ) Product.joins(sm_table.join_sources).joins(md_table.join_sources) 

SQL

 SELECT products.* FROM products INNER JOIN variants on variants.product_id = products.id AND variants.size = 'SM' INNER JOIN variants on variants.product_id = products.id AND variants.size = 'MD' 

由于INNER JOIN,这两个连接应该强制执行小型和中型

恕我直言,你需要使用更多的SQL而不是Rails魔术来构建这样的数据库查询。

 Product .joins('INNER JOIN variants as sm_vs ON sm_vs.product_id = products.id') .joins('INNER JOIN variants as md_vs ON md_vs.product_id = products.id') .where(sm_vs: { size: 'SM' }) .where(md_vs: { size: 'MD' }) 

或简化 – 正如@engineersmnky建议:

 Product .joins("INNER JOIN variants as sm_vs ON sm_vs.product_id = products.id AND sm_vs.size = 'SM'") .joins("INNER JOIN variants as md_vs ON md_vs.product_id = products.id AND sm_vs.size = 'MD'") 

两个查询基本相同。 只需选择您喜欢的版本。

Product.joins(:variants).where(’variants.size =?OR variants.size =?’,’SM’,’MD’)