Rails关联查询问题:如何筛选仅销售衬衫的Store?
解决Rails中has_many关联查询仅销售特定商品的店铺问题
我明白你的困扰!你当前的查询只是筛选出了包含衬衫商品的店铺,但没有排除那些同时售卖其他商品的店铺(比如Macy's和Target还卖裤子)。要找到仅销售衬衫的店铺,我们需要确保这些店铺的所有商品都是衬衫,或者说它们不存在任何非衬衫的商品。
为什么你的原查询不符合需求?
你的代码:
Store.includes(:items).where( items: { name: %w(shirt)} ).references(:items)
本质是做了一次关联查询,只要店铺有至少一件衬衫,就会被返回,完全没考虑店铺是否还有其他类型的商品,所以会包含ID为1、2、3的所有店铺。
正确的解决方案
这里提供几种高效的实现方式:
方法1:用子查询排除售卖非衬衫商品的店铺
Store.where.not(id: Item.where.not(name: 'shirt').select(:store_id))
这个逻辑很直接:先找出所有卖过非衬衫商品的店铺ID,然后排除这些ID,剩下的就是只卖衬衫的店铺。
方法2:用GROUP BY + HAVING统计商品种类
Store.joins(:items) .group('stores.id') .having('COUNT(DISTINCT items.name) = 1') .where(items: { name: 'shirt' })
步骤拆解:
- 关联店铺和商品表
- 按店铺ID分组
- 筛选出商品种类只有1种,且该种类是衬衫的店铺
方法3:用EXISTS子查询确保无其他商品
Store.where( 'NOT EXISTS ( SELECT 1 FROM items WHERE items.store_id = stores.id AND items.name != ? )', 'shirt' )
这个写法直接检查:对于每个店铺,不存在任何名字不是衬衫的商品,符合条件的店铺就会被返回。
以上三种方法都能准确返回ID为3的Dillards店铺,你可以根据自己的习惯和项目的性能需求选择合适的写法~
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

