Einige wichtige Punkte zur Verwendung von SQL:
- Sie können keine Spaltenaliase in der WHERE-Klausel verwenden, aber Sie können dies in der HAVING-Klausel tun. Das ist die Ursache für den Fehler, den Sie erhalten haben.
- Sie können Ihre Zählung mit JOIN und GROUP BY besser durchführen als mit korrelierten Unterabfragen. Das geht viel schneller.
- Verwenden Sie die HAVING-Klausel, um Gruppen zu filtern.
So würde ich diese Abfrage schreiben:
SELECT t1.id, COUNT(t2.id) AS num_things
FROM t1 JOIN t2 USING (id)
GROUP BY t1.id
HAVING num_things = 5;
Mir ist klar, dass diese Abfrage den JOIN
überspringen kann mit t1, wie in der Lösung von Charles Bretana. Aber ich nehme an, Sie möchten vielleicht, dass die Abfrage einige andere Spalten von t1 enthält.
Betreff:die Frage im Kommentar:
Der Unterschied besteht darin, dass der WHERE
-Klausel wird für Zeilen vor GROUP BY
ausgewertet reduziert Gruppen auf eine einzelne Zeile pro Gruppe. Das HAVING
-Klausel wird ausgewertet, nachdem Gruppen gebildet wurden. Sie können also beispielsweise COUNT()
nicht ändern einer Gruppe mit HAVING
; Sie können nur die Gruppe selbst ausschließen.
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;
In der obigen Abfrage WHERE
filtert nach Zeilen, die einer Bedingung entsprechen, und HAVING
filtert nach Gruppen, die mindestens fünf zählen.
Der Punkt, der die meisten Leute verwirrt, ist, wenn sie kein GROUP BY
haben Klausel, so scheint es wie HAVING
und WHERE
sind austauschbar.
WHERE
wird vor Ausdrücken in der Auswahlliste ausgewertet. Dies ist möglicherweise nicht offensichtlich, da die SQL-Syntax die Auswahlliste an die erste Stelle setzt. Sie können also eine Menge teurer Berechnungen sparen, indem Sie WHERE
verwenden um Zeilen einzuschränken.
SELECT <expensive expressions>
FROM t1
HAVING primaryKey = 1234;
Wenn Sie eine Abfrage wie oben verwenden, werden die Ausdrücke in der Auswahlliste für jede Zeile berechnet , nur um die meisten Ergebnisse wegen HAVING
zu verwerfen Bedingung. Die folgende Abfrage berechnet den Ausdruck jedoch nur für die einzelne Zeile passend zum WHERE
Zustand.
SELECT <expensive expressions>
FROM t1
WHERE primaryKey = 1234;
Um es noch einmal zusammenzufassen:Abfragen werden von der Datenbank-Engine gemäß einer Reihe von Schritten ausgeführt:
- Zeilensatz aus Tabelle(n) generieren, einschließlich aller durch
JOIN
erzeugten Zeilen . - Werte
WHERE
aus Bedingungen gegen den Satz von Zeilen, wobei Zeilen herausgefiltert werden, die nicht übereinstimmen. - Berechnen Sie Ausdrücke in der Auswahlliste für jede in der Reihe von Zeilen.
- Spaltenaliase anwenden (beachten Sie, dass dies ein separater Schritt ist, was bedeutet, dass Sie keine Aliase in Ausdrücken in der Auswahlliste verwenden können).
- Verdichten Sie Gruppen gemäß
GROUP BY
zu einer einzigen Zeile pro Gruppe Klausel. - Bewerten Sie
HAVING
Bedingungen gegen Gruppen, wobei Gruppen herausgefiltert werden, die nicht übereinstimmen. - Ergebnis sortieren, nach
ORDER BY
Klausel.