2016-08-01 73 views
0

有兩個表:用戶和教師。 Teacher.user_id來自用戶。那麼,如何在單個查詢中找到所有不在教師中的用戶。其他表中未引用的回溯記錄,ActiveRecord查詢

我的意思是沿着線的東西:

  User.not_in(Teacher.all) 
+1

你確定你不是指「數據庫表」而不是「數據庫」嗎? –

+0

糟糕。我正是這個意思。我是一名鐵桿新手。所以,我可以互換使用它 –

回答

0

您可以使用where.not查詢從ActiveRecord嘗試類似如下:

User.where.not(id: Teacher.pluck(:user_id).reject {|x| x.nil?}) 

注:使用reject方法,以防在某些記錄中有零值。

+1

因此完美無瑕。非常感謝。 –

+0

很高興它的工作,但我也建議考慮其他答案http://stackoverflow.com/a/38706214/2545197以及。 – Abhinay

+1

看來你認爲這是不正確的,雖然在這種情況下,我仍然會考慮我們在我的帖子中討論過的內容,因爲如果教師表變得太大,SQL將失敗,因爲查詢只能是這麼多字符長,而'Array'可能會導致它超過這個值。簡單的解決方法是將pluck版本更改爲'Teacher.where.not(id:nil).select(:user_id)',那麼它將執行'reject'部分作爲子查詢。 – engineersmnky

0

我想你應該能夠做這樣的事

User.where.not(id: Teacher.ids) 
+0

這不會起作用,您應該將'user_id'傳遞給它而不是'teacher_id' – Abhinay

1

其他用戶似乎已經忽略了導軌3標籤(因爲根據批准的答案刪除離開我的回答給後人。):請試試這個

User.where("id NOT IN (?)",Teacher.pluck(:user_id).join(",")) 

這將成爲SELECT * FROM users WHERE id NOT IN (....)(兩個查詢之一從老師那裏得到user_id,而另一個得到user(s)不在該列表中)並且可能基於老師表的大小而失敗。

其他選項是AREL表:

users = User.arel_table 
User.where(users[:id].not_in(Teacher.select(:user_id).where("user_id IS NOT NULL"))) 

這應該產生類似於

SELECT * FROM users 
WHERE id NOT IN (SELECT user_id FROM teachers WHERE user_id IS NOT NULL) 

(一個查詢性能越好)單查詢*語法不完全測試

另一個單個查詢選項可能是

User.joins("LEFT OUTER JOIN teachers ON teachers.user_id = users.id"). 
    where("teachers.user_id IS NULL") 
+0

嘿,我完全同意你在這裏的觀點,但不是它仍然運行兩個查詢? – Abhinay

+0

@Abhinay它不需要SQL返回程序構建一個'Array',然後執行第二個查詢,因爲'pluck'方法需要這個。相反,整個查詢在SQL服務器上執行,只返回所需的結果。但從技術上講,你可以看到子查詢作爲第二個查詢,因此輸入我的第三個建議,這是真正的1查詢。 – engineersmnky

+0

明白了,謝謝你的解釋。順便說一句,用戶問這個問題的方式,我懷疑他真的意味着rails-3版本。他提到了成爲一名新手 – Abhinay

相關問題