查找一对多连接表满足一个条件但不满足另一个条件的所有记录

时间:2015-05-03 22:45:45

标签: mysql sql ruby-on-rails

我希望所有拥有至少一个类型" Apple"的酒吧的Foos,但也没有一个类型为" Orange"在架构中:

Foo
----
id

Bar
----
id
foo_id
type

如果我的数据是这样的:

Foos
----
| id |
| 1  |
| 2  |
| 3  |

Bars
----
| id | foo_id | type   |
| 1  | 1      | Apple  |
| 2  | 1      | Orange |
| 3  | 3      | Apple  |

此查询仅返回ID = 3的Foo,因为1有Apple但有橙色,2有橙色但没有Apple。

此外,我将使用Rails标记此帖子,因为ActiveRecord解决方案将是首选但不是必需的。

2 个答案:

答案 0 :(得分:0)

您可以使用sql

SELECT foo_id FROM test.bars GROUP BY foo_id  HAVING SUM(IF(type = 'Apple',1,0)) > 0 AND SUM(IF(type = 'Orange',1,0)) = 0 ;

或在ActiveRecord中相同:

bars.group(:foo_id).having('SUM(IF(type = "Apple",1,0)) > ?',0).having('SUM(IF(type = "Orange",1,0)) = ?', 0)

答案 1 :(得分:0)

我认为最好用子查询来做这件事。 SQL:

Foo.find_by_sql("SELECT f.* FROM foo f WHERE 
  f.id IN (SELECT foo_id FROM bar x WHERE x.type='Apple') AND
  f.id NOT IN (SELECT foo_id FROM bar WHERE x.type='Orange')")

AREL:

Foo.where(id: Bar.select("foo_id").where(type: 'Apple'))
   .where.not(id: Bar.select("foo_id").where(type: 'Orange'))

我在自己的架构中测试了这两种方式,所以我提前为任何转换到您域名的拼写错误道歉。