Beberapa poin penting tentang penggunaan SQL:
- Anda tidak dapat menggunakan alias kolom dalam klausa WHERE, tetapi Anda dapat menggunakan klausa HAVING. Itulah penyebab kesalahan yang Anda dapatkan.
- Anda dapat menghitung lebih baik menggunakan JOIN dan GROUP BY daripada menggunakan subkueri yang berkorelasi. Ini akan jauh lebih cepat.
- Gunakan klausa HAVING untuk memfilter grup.
Inilah cara saya menulis kueri ini:
SELECT t1.id, COUNT(t2.id) AS num_things
FROM t1 JOIN t2 USING (id)
GROUP BY t1.id
HAVING num_things = 5;
Saya menyadari kueri ini dapat melewati JOIN
dengan t1, seperti dalam solusi Charles Bretana. Tapi saya berasumsi Anda mungkin ingin kueri menyertakan beberapa kolom lain dari t1.
Re:pertanyaan di komentar:
Perbedaannya adalah WHERE
klausa dievaluasi pada baris, sebelum GROUP BY
mengurangi grup menjadi satu baris per grup. HAVING
klausa dievaluasi setelah kelompok terbentuk. Jadi, Anda tidak dapat, misalnya, mengubah COUNT()
grup dengan menggunakan HAVING
; Anda hanya dapat mengecualikan grup itu sendiri.
SELECT t1.id, COUNT(t2.id) as num
FROM t1 JOIN t2 USING (id)
WHERE t2.attribute = <value>
GROUP BY t1.id
HAVING num > 5;
Dalam kueri di atas, WHERE
filter untuk baris yang cocok dengan kondisi, dan HAVING
filter untuk grup yang memiliki setidaknya lima hitungan.
Hal yang membuat kebanyakan orang kebingungan adalah ketika mereka tidak memiliki GROUP BY
klausa, jadi sepertinya seperti HAVING
dan WHERE
dapat dipertukarkan.
WHERE
dievaluasi sebelum ekspresi dalam daftar pilih. Ini mungkin tidak jelas karena sintaks SQL menempatkan daftar pilih terlebih dahulu. Jadi Anda dapat menghemat banyak komputasi mahal dengan menggunakan WHERE
untuk membatasi baris.
SELECT <expensive expressions>
FROM t1
HAVING primaryKey = 1234;
Jika Anda menggunakan kueri seperti di atas, ekspresi dalam daftar pilih dihitung untuk setiap baris , hanya untuk membuang sebagian besar hasil karena HAVING
kondisi. Namun, kueri di bawah menghitung ekspresi hanya untuk baris tunggal cocok dengan WHERE
kondisi.
SELECT <expensive expressions>
FROM t1
WHERE primaryKey = 1234;
Jadi untuk rekap, kueri dijalankan oleh mesin basis data menurut serangkaian langkah:
- Buat kumpulan baris dari tabel, termasuk baris apa pun yang dihasilkan oleh
JOIN
. - Evaluasi
WHERE
kondisi terhadap kumpulan baris, memfilter baris yang tidak cocok. - Hitung ekspresi dalam daftar-pilih untuk setiap set baris.
- Terapkan alias kolom (perhatikan ini adalah langkah terpisah, yang berarti Anda tidak dapat menggunakan alias dalam ekspresi di daftar pilih).
- Singkat grup menjadi satu baris per grup, menurut
GROUP BY
klausa. - Evaluasi
HAVING
ketentuan terhadap grup, menyaring grup yang tidak cocok. - Urutkan hasil, menurut
ORDER BY
klausa.