Melakukan gabungan dalam ke tabel has_many yang dikombinasikan dengan group
atau uniq
berpotensi sangat tidak efisien, dan dalam SQL ini akan lebih baik diimplementasikan sebagai gabungan semi yang menggunakan EXISTS
dengan subkueri berkorelasi.
Ini memungkinkan pengoptimal kueri untuk menyelidiki tabel lowongan untuk memeriksa keberadaan baris dengan project_id yang benar. Tidak masalah apakah ada satu baris atau sejuta yang memiliki project_id tersebut.
Itu tidak semudah di Rails, tetapi bisa dicapai dengan:
Project.where(Vacancies.where("vacancies.project_id = projects.id").exists)
Demikian pula, temukan semua proyek yang tidak memiliki lowongan:
Project.where.not(Vacancies.where("vacancies.project_id = projects.id").exists)
Sunting: dalam versi Rails terbaru Anda mendapatkan peringatan penghentian yang memberitahu Anda untuk tidak mengandalkan exists
pendelegasian ke arel. Perbaiki ini dengan:
Project.where.not(Vacancies.where("vacancies.project_id = projects.id").arel.exists)
Sunting: jika Anda tidak nyaman dengan SQL mentah, coba:
Project.where.not(Vacancies.where(Vacancy.arel_table[:project_id].eq(Project.arel_table[:id])).arel.exists)
Anda dapat mengurangi kekacauan ini dengan menambahkan metode kelas untuk menyembunyikan penggunaannya arel_table
, misalnya:
class Project
def self.id_column
arel_table[:id]
end
end
... jadi ...
Project.where.not(
Vacancies.where(
Vacancy.project_id_column.eq(Project.id_column)
).arel.exists
)