Kilka ważnych punktów dotyczących używania SQL:
- Nie możesz używać aliasów kolumn w klauzuli WHERE, ale możesz w klauzuli HAVING. To jest przyczyna otrzymanego błędu.
- Możesz lepiej liczyć, używając funkcji JOIN i GROUP BY niż za pomocą skorelowanych podzapytań. Będzie znacznie szybciej.
- Użyj klauzuli HAVING do filtrowania grup.
Oto sposób, w jaki napisałbym to zapytanie:
SELECT t1.id, COUNT(t2.id) AS num_things
FROM t1 JOIN t2 USING (id)
GROUP BY t1.id
HAVING num_things = 5;
Zdaję sobie sprawę, że to zapytanie może pominąć JOIN
z t1, jak w rozwiązaniu Charlesa Bretany. Ale zakładam, że możesz chcieć, aby zapytanie zawierało inne kolumny z t1.
Re:pytanie w komentarzu:
Różnica polega na tym, że WHERE
klauzula jest oceniana w wierszach, przed GROUP BY
redukuje grupy do jednego wiersza na grupę. HAVING
klauzula jest oceniana po utworzeniu grup. Nie możesz więc na przykład zmienić COUNT()
grupy za pomocą HAVING
; możesz wykluczyć tylko samą grupę.
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;
W powyższym zapytaniu WHERE
filtry dla wierszy pasujących do warunku i HAVING
filtry dla grup, które mają co najmniej pięć liczników.
Punktem, który powoduje zamieszanie u większości ludzi, jest to, że nie mają GROUP BY
klauzula, więc wydaje się jak HAVING
i WHERE
są wymienne.
WHERE
jest oceniany przed wyrażeniami na liście wyboru. Może to nie być oczywiste, ponieważ składnia SQL umieszcza listę wyboru na pierwszym miejscu. Możesz więc zaoszczędzić wiele kosztownych obliczeń, używając WHERE
aby ograniczyć wiersze.
SELECT <expensive expressions>
FROM t1
HAVING primaryKey = 1234;
Jeśli używasz zapytania takiego jak powyżej, wyrażenia na liście wyboru są obliczane dla każdego wiersza , tylko po to, aby odrzucić większość wyników z powodu HAVING
stan. Jednak poniższe zapytanie oblicza wyrażenie tylko dla pojedynczego wiersza pasujące do WHERE
stan.
SELECT <expensive expressions>
FROM t1
WHERE primaryKey = 1234;
Podsumowując, zapytania są uruchamiane przez silnik bazy danych zgodnie z serią kroków:
- Wygeneruj zestaw wierszy z tabel, w tym wiersze utworzone przez
JOIN
. - Oceń
WHERE
warunki względem zestawu wierszy, odfiltrowując wiersze, które nie pasują. - Oblicz wyrażenia na liście wyboru dla każdego w zestawie wierszy.
- Zastosuj aliasy kolumn (pamiętaj, że jest to osobny krok, co oznacza, że nie możesz używać aliasów w wyrażeniach na liście wyboru).
- Skondensuj grupy w jednym wierszu na grupę, zgodnie z
GROUP BY
klauzula. - Oceń
HAVING
warunki przeciwko grupom, odfiltrowując grupy, które nie pasują. - Sortuj wyniki według
ORDER BY
klauzula.