Realizar una unión interna a la tabla has_many combinada con un group
o uniq
es potencialmente muy ineficiente, y en SQL esto se implementaría mejor como una semi-unión que se usa EXISTS
con una subconsulta correlacionada.
Esto permite al optimizador de consultas sondear la tabla de vacantes para verificar la existencia de una fila con el project_id correcto. No importa si hay una fila o un millón que tienen ese project_id.
Eso no es tan sencillo en Rails, pero se puede lograr con:
Project.where(Vacancies.where("vacancies.project_id = projects.id").exists)
Del mismo modo, busque todos los proyectos que no tengan vacantes:
Project.where.not(Vacancies.where("vacancies.project_id = projects.id").exists)
Editar: en las versiones recientes de Rails, recibe una advertencia de desaprobación que le indica que no dependa de exists
ser delegado a arel. Arregle esto con:
Project.where.not(Vacancies.where("vacancies.project_id = projects.id").arel.exists)
Editar: si no se siente cómodo con SQL sin formato, intente:
Project.where.not(Vacancies.where(Vacancy.arel_table[:project_id].eq(Project.arel_table[:id])).arel.exists)
Puede hacer que esto sea menos complicado agregando métodos de clase para ocultar el uso de arel_table
, por ejemplo:
class Project
def self.id_column
arel_table[:id]
end
end
... entonces ...
Project.where.not(
Vacancies.where(
Vacancy.project_id_column.eq(Project.id_column)
).arel.exists
)