【问题标题】:Find all records where one-to-many join table satisfies one condition, but not another condition查找一对多连接表满足一个条件但不满足另一个条件的所有记录
【发布时间】:2015-05-03 22:45:45
【问题描述】:

我想获取所有 Foos,它们至少有一个类型为“Apple”的 Bar,但在架构中也没有类型为“Orange”的 Bar:

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,但也有一个 Orange,而 2 没有 Orange,但也没有 Apple。

另外,我将用 Rails 标记这篇文章,因为 ActiveRecord 解决方案是首选但不是必需的。

【问题讨论】:

  • FooBar 是否相关类?如果有,怎么做?
  • 是的,Foo 有很多 Bars(如 foo_id 所示)。

标签: mysql sql ruby-on-rails


【解决方案1】:

我认为最好使用子查询来做到这一点。 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')")

阿雷尔:

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

我在自己的架构中测试了两种方式,因此对于转换为您的域的任何拼写错误,我提前道歉。

【讨论】:

  • 当然洛根很乐意提供帮助
【解决方案2】:

你可以使用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)

【讨论】:

  • 第二个查询不会返回Bars 的集合,而不是Foos?
猜你喜欢
  • 1970-01-01
  • 2021-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-14
  • 2020-03-08
  • 1970-01-01
相关资源
最近更新 更多