Виконання внутрішнього приєднання до таблиці has_many у поєднанні з group
або uniq
є потенційно дуже неефективним, а в SQL це було б краще реалізовано як напівз'єднання, яке використовує EXISTS
з корельованим підзапитом.
Це дозволяє оптимізатору запитів перевірити таблицю вакансій, щоб перевірити наявність рядка з правильним project_id. Не має значення, чи є один ряд чи мільйон, які мають цей проект_id.
Це не так просто в Rails, але це може бути досягнуто за допомогою:
Project.where(Vacancies.where("vacancies.project_id = projects.id").exists)
Аналогічно знайдіть усі проекти, у яких немає вакансій:
Project.where.not(Vacancies.where("vacancies.project_id = projects.id").exists)
Редагувати: в останніх версіях Rails ви отримуєте попередження про exists
зняття з експлуатації, яке говорить про те, що ви не покладаєтесь на делегування на arel. Виправте це за допомогою:
Project.where.not(Vacancies.where("vacancies.project_id = projects.id").arel.exists)
Редагувати: якщо вам незручно із сирим SQL, спробуйте:
Project.where.not(Vacancies.where(Vacancy.arel_table[:project_id].eq(Project.arel_table[:id])).arel.exists)
Ви можете зробити це менш безладним, додавши методи класу, щоб приховати використання arel_table
, наприклад:
class Project
def self.id_column
arel_table[:id]
end
end
... так ...
Project.where.not(
Vacancies.where(
Vacancy.project_id_column.eq(Project.id_column)
).arel.exists
)