请帮忙!
我需要将下面的查询子句合并为一个。
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如果栏同时存在。
答案 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)
joins
为INNER JOIN
您需要的是OUTER JOIN