2014-04-16 14 views
7

Zamierzam zapytać wszystkich użytkowników bez komentarzy w jednym zapytaniu sql?Rails User.joins.not (...) w Active Record?

Modele:

class User < ActiveRecord::Base 
    has_many :comments 
end 

class Comment < ActiveRecord::Base 
    belongs_to :user 
end 

Więc chcę przeciwieństwo tego:

User.joins.(:comments).group('users.id') 

Ale nie tak: (ponieważ generuje dwa zapytań)

User.where.not(id: Comment.pluck(:user_id)) 

może coś podobnego to?

User.joins.not.(:comments).group('users.id') 

Dzięki za wszelkie dane wejściowe!

+0

Spróbuj 'User.includes (: komentarze) .gdzie (komentarze: {id: nil})' – MrYoshiji

Odpowiedz

11

Można zrobić coś jak

User.where.not(id: Comment.select(:user_id)) 

Jeśli chciałeś jeden (choć zagnieżdżone) zapytania.

W przeciwnym razie sprawdź, czy w przypadku łączenia zewnętrznego nie ma wartości http://guides.rubyonrails.org/active_record_querying.html#joining-tables.

+1

użyje podzapytania lub 2 różnych kwerend? – thethanghn

+2

@thethanghn w tym przypadku spowoduje sub-zapytanie. Za każdym razem, gdy przekażesz 'ActiveRecord :: Relation' (czyli to, co metody zapytań aktywnych rekordów, takie jak' select' i 'where' return) do metody zapytania, zostanie wygenerowane zapytanie podrzędne. –

2

Jeśli używasz postgresql można zrobić coś takiego

User.joins("LEFT join comments c on users.id = c.comment_id"). 
select("users.id"). 
group("users.id"). 
having("count(users.id) = 1") 

To wygeneruje to zapytanie

select u.id from users u 
LEFT join comments c 
on c.comment_id = u.id 
group by u.id 
having count(u.id) = 1 

To zapytanie nie generuje dwa SQL (ani zagnieżdżony SQL), powyższa odpowiedź robi.

+0

Co oznacza skrót "c" i "u" w tym zapytaniu? – thiebo

+1

@thiebo "c" jest aliasem dla tabeli komentarzy, a "u" jest aliasem dla tabeli użytkowników. Możesz znaleźć więcej informacji na temat aliasów SQL [tutaj] (https://en.wikipedia.org/wiki/Alias_ (SQL)) –

0

Innym prostym rozwiązaniem User.where("id NOT IN (?)", Comment.pluck(:user_id))

Powiązane problemy