簡體   English   中英

Rails如何在不存在實例的情況下查詢has_many實例

[英]Rails how to query has_many instance in condition of the instance not exist

請幫忙!

我需要將以下查詢子句合並為一個。

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

joins(:bar) in子句時, bar_id IS NULL記錄將被過濾。

像下面這樣組合起來並不是那么簡單,此bar_id IS NULL將被過濾。

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

我想要的結果更像

bar_id is null or (bar_id is not null AND bars.daily_budget > bars.daily_cost)

Foo結果需要bar_id為null,並且bar.daily_budget> bars.daily_cost如果bar同時存在。

您真正想要的是SQL UNION。

您可以使用#or查詢方法。 竅門是,您必須在兩端都使用joins(:bar) 才能將Relation傳遞給#,或者必須在結構上兼容。

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)

注意 :QueryMethod or已在Rails 5中添加。

更新 :正如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)

調用.joins(:bar)在於,它將默認創建一個INNER JOIN數據庫查詢。 發生這種情況時,結果中將不包含bar_id為null的記錄。 並且指定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')

請注意,您的情況下的表名很可能是復數形式,因此請確保查詢與您的環境匹配。

joins Rails是INNER JOIN您需要的是OUTER JOIN

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM