3

у меня есть что-то похожее на следующие 2 модели:ActiveRecord запрос для модели не упоминается в другой модели

class Person < ActiveRecord::Base 
    has_one :student 
end 
class Student < ActiveRecord::Base 
    belongs_to :person 
end 

Я знаю, что могу найти всех людей, которые студенты с:

Person.joins(:student) 

Как может Я нахожу всех людей, которые не студентов? Есть ли способ сделать это с помощью ActiveRecord и не писать SQL-запрос?

ответ

2

Используйте это заявление:

Person.includes(:student). 
     where(:students => {:id => nil}) 

или

Person.joins("LEFT JOIN students ON students.person_id = people.id"). 
     where(:students => {:id => nil}) 

Я предпочитаю последний, потому что это Безразлично Не выбирайте ненужные столбцы.

+0

Вы правы. Мне нравится второе заявление. Я не знаю, какая производительность попадала на подзапрос в PostgreSQL (база данных, которую мы используем в процессе производства). Я надеялся, что это будет оптимизировано, чтобы быть очень эффективным. –

1

Поскольку вы используете рельсы 4 вы можете сделать это следующим образом:

Person.where.not(:id => Student.select(:person_id)) 
+0

Запрос, который он производит, выглядит хорошо, но не возвращает никаких строк (когда это должно): 'SELECT" people ". * FROM" people "WHERE (" people "." Id "NOT IN (SELECT" students " . "person_id" FROM "students")) '. У меня много объектов 'Person' в базе данных,' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' Интересно, что если я выберу «не» из запроса, я получу правильных людей, которые являются студентами. Я просто не понимаю, когда «нет». –

+0

Причина, по которой он не работал для меня, - это поля 'nil'' person_id' в 'Student'. Итак, это запрос, который работает для меня: 'Person.where.not (id: Student.select (: person_id) .where.not (person_id: nil))' –

+0

Опасайтесь: это два запроса! И 'Student.select (: person_id)' извлекает много данных из базы данных, если таблица Student является большой. См. Мой ответ для лучшего решения. –

Смежные вопросы