Een paar belangrijke punten over het gebruik van SQL:
- Je kunt geen kolomaliassen gebruiken in de WHERE-component, maar wel in de HAVING-component. Dat is de oorzaak van de fout die je hebt gekregen.
- U kunt uw telling beter doen met JOIN en GROUP BY dan met gecorreleerde subquery's. Het zal veel sneller zijn.
- Gebruik de HAVING-component om groepen te filteren.
Dit is de manier waarop ik deze vraag zou schrijven:
SELECT t1.id, COUNT(t2.id) AS num_things
FROM t1 JOIN t2 USING (id)
GROUP BY t1.id
HAVING num_things = 5;
Ik realiseer me dat deze zoekopdracht de JOIN
kan overslaan met t1, zoals in de oplossing van Charles Bretana. Maar ik neem aan dat je misschien wilt dat de query een aantal andere kolommen van t1 bevat.
Re:de vraag in de reactie:
Het verschil is dat de WHERE
clausule wordt geëvalueerd op rijen, vóór GROUP BY
reduceert groepen tot één rij per groep. De HAVING
clausule wordt geëvalueerd nadat groepen zijn gevormd. U kunt dus bijvoorbeeld de COUNT()
. niet wijzigen van een groep met behulp van HAVING
; je kunt alleen de groep zelf uitsluiten.
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 de bovenstaande zoekopdracht, WHERE
filters voor rijen die overeenkomen met een voorwaarde, en HAVING
filters voor groepen die ten minste vijf tellen.
Het punt dat de meeste mensen in verwarring brengt, is wanneer ze geen GROUP BY
. hebben clausule, dus het lijkt zoals HAVING
en WHERE
zijn uitwisselbaar.
WHERE
wordt geëvalueerd vóór expressies in de selectielijst. Dit is misschien niet voor de hand liggend omdat de SQL-syntaxis de selectielijst als eerste plaatst. U kunt dus veel dure berekeningen besparen door WHERE
. te gebruiken om rijen te beperken.
SELECT <expensive expressions>
FROM t1
HAVING primaryKey = 1234;
Als u een zoekopdracht zoals hierboven gebruikt, worden de uitdrukkingen in de selectielijst berekend voor elke rij , alleen om de meeste resultaten weg te gooien vanwege de HAVING
voorwaarde. De onderstaande query berekent de uitdrukking echter alleen voor de enkele rij overeenkomend met WHERE
staat.
SELECT <expensive expressions>
FROM t1
WHERE primaryKey = 1234;
Dus om samen te vatten, query's worden uitgevoerd door de database-engine volgens een reeks stappen:
- Genereer een set rijen uit tabel(len), inclusief alle rijen geproduceerd door
JOIN
. - Evalueer
WHERE
voorwaarden tegen de reeks rijen, waarbij rijen worden uitgefilterd die niet overeenkomen. - Bereken expressies in de selectielijst voor elk in de reeks rijen.
- Kolomaliassen toepassen (merk op dat dit een aparte stap is, wat betekent dat u geen aliassen kunt gebruiken in expressies in de selectielijst).
- Condens groepen tot een enkele rij per groep, volgens
GROUP BY
clausule. - Evalueer
HAVING
voorwaarden tegen groepen, waarbij groepen worden uitgefilterd die niet overeenkomen. - Sorteer resultaat, volgens
ORDER BY
clausule.