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
WHEREkondisi 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 BYklausa. - Evaluasi
HAVINGketentuan terhadap grup, menyaring grup yang tidak cocok. - Urutkan hasil, menurut
ORDER BYklausa.