Rails如何在实例不存在的情况下查询has_many实例

时间:2017-09-08 06:01:51

标签: mysql sql ruby-on-rails ruby-on-rails-4

请帮忙!

我需要将下面的查询子句合并为一个。

mano

Foo.where('bar_id IS NULL') Foo.joins(:bar).where('bar.daily_budget > bar.daily_cost') in子句中,joins(:bar)记录将被过滤。

如下所示组合起来并不那么简单,此bar_id IS NULL将被过滤。

bar_id IS NULL

我想要的结果更像是

Foo.joins(:bar).where('bar.daily_budget > bar.daily_cost').where('bar_id IS NULL')

Foo结果需要bar_id为null,并且bars.daily_budget> bars.daily_cost如果栏同时存在。

3 个答案:

答案 0 :(得分:1)

你真正想要的是SQL UNION。

您可以使用#or查询方法。诀窍是,你必须在两端使用joins(:bar) 传递给#or的关系必须在结构上兼容。

Foo.joins(:bar).where(:bar_id => nil)
               .or(Foo.join(:bar).where('bar.daily_budget > bar.daily_cost'))
# SELECT `foos`.* FROM `foos` INNER JOIN `bar` on `foos.bar_id` = `bar.id` WHERE(`foos`.`bar_id` is NULL OR bar.daily_budget > bar.daily_cost)

注意:在Rails 5中添加了QueryMethod or

更新:正如DanneManne回答的那样,上面的工作没有成功,因为.joins(:bar).where(:bar_id => nil)实际上对INNER JOIN没有任何帮助。所需要的是LEFT JOIN,可以通过以下方式完成:

Foo.left_outer_joins(:bar).where('foo.bar_id is null or bar.daily_budget > bar.daily_cost')
SELECT `foos`.* from `foos` LEFT OUTER JOIN `bar` ON `foos`.`bar_id` = `bar`.`id` WHERE (foo.bar_id is null or bar.daily_budget > bar.daily_cost)

答案 1 :(得分:1)

调用.joins(:bar)的问题是它默认会创建一个INNER JOIN数据库查询。当发生这种情况时,bar_id为空的记录将不包含在结果中。并且指定where(bar_id: null)不会改变它。

但是,您可以通过将LEFT OUTER JOIN字符串传递给joins方法而不是符号来解决此问题,并从那里开始工作。例如:

Foo.joins('LEFT OUTER JOIN bar ON foo.bar_id = bar.id')
   .where('foo.bar_id IS NULL OR bar.daily_budget > bar.daily_cost')

请注意,您的案例中的表名很可能是复数,因此请确保查询符合您的环境。

答案 2 :(得分:0)

Rails中的

joinsINNER JOIN 您需要的是OUTER JOIN