首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rails查找具有两个具有特定属性的子项的父项

Rails查找具有两个具有特定属性的子项的父项
EN

Stack Overflow用户
提问于 2017-07-04 00:06:12
回答 3查看 1.1K关注 0票数 2

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

到目前为止,我可以得到所有具有size属性'SM‘的变体的产品。

挂断,是得到所有的产品,都有一个变种与大小'MD‘和'SM’。

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

我尝试将.where('variants.size = ?', 'MD')添加到其中,但它确实起作用了。

EN

回答 3

Stack Overflow用户

发布于 2017-07-04 00:48:31

这个怎么样?

代码语言:javascript
复制
Product.where(
 id: Variant.select(:product_id)
     .where(size: 'SM')
).where(id: Variant.select(:product_id)
    .where(size: 'MD')
)

这应该会生成类似于

代码语言:javascript
复制
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%确定)

代码语言:javascript
复制
Product.where(id: Product.joins(:variants)
                 .where(variants: {size: ['SM', 'MD']})
                 .group(:id)
                 .having('COUNT(*) = 2').select(:id)

这应该会生成类似这样的结果

代码语言:javascript
复制
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  

再多一个选择

代码语言:javascript
复制
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

代码语言:javascript
复制
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'

由于内部连接,这两个连接应强制执行small和medium

票数 4
EN

Stack Overflow用户

发布于 2017-07-04 00:37:51

我想你需要使用更多的SQL而不是Rails的魔法来构建这样的数据库查询。

代码语言:javascript
复制
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建议的那样简化:

代码语言:javascript
复制
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'")

这两个查询的功能基本相同。只要选择你更喜欢的版本即可。

票数 2
EN

Stack Overflow用户

发布于 2017-07-04 00:15:23

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

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44889960

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档