Ruby Rails查询无关联Price或无active状态Price的Item记录
优化方案分析
首先你的原始代码存在逻辑问题:第二个条件where.not(prices: {status: 'active'})会匹配至少有一个Price状态不为active的Item,但如果某个Item同时存在active和非active的Price,这个条件依然会把它纳入结果,不符合你“只要有一个active Price就排除”的需求。
下面是两种更可靠且高效的实现方式:
方式一:子查询排除法(推荐)
这种写法简洁直观,性能也更优(若prices表有status和item_id的联合索引则效果更好):
Item.where.not(id: Price.where(status: 'active').select(:item_id))
逻辑说明:
- 先通过子查询找出所有关联了
status = 'active'的Price的Item ID集合 - 取不在这个集合里的所有Item,自然包含了没有任何Price记录的Item(它们的ID不会出现在子查询结果中)
方式二:左连接+分组统计法
适合需要在查询中附加更多统计逻辑的场景:
Item.left_joins(:prices) .group('items.id') .having('COUNT(prices.id) = 0 OR SUM(CASE WHEN prices.status = ? THEN 1 ELSE 0 END) = 0', 'active')
逻辑说明:
left_joins(:prices)保证没有Price关联的Item也会被查询到- 按Item ID分组后,通过
having条件过滤:COUNT(prices.id) = 0:匹配没有任何Price记录的ItemSUM(...) = 0:匹配所有关联的Price中,没有status = 'active'的Item
内容的提问来源于stack exchange,提问作者yeahNah
相关产品推荐
相关产品推荐

