sql >> Database >  >> RDS >> PostgreSQL

PostgreSQL - Gecorreleerde subquery mislukt?

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:

  1. Genereer een set rijen uit tabel(len), inclusief alle rijen geproduceerd door JOIN .
  2. Evalueer WHERE voorwaarden tegen de reeks rijen, waarbij rijen worden uitgefilterd die niet overeenkomen.
  3. Bereken expressies in de selectielijst voor elk in de reeks rijen.
  4. Kolomaliassen toepassen (merk op dat dit een aparte stap is, wat betekent dat u geen aliassen kunt gebruiken in expressies in de selectielijst).
  5. Condens groepen tot een enkele rij per groep, volgens GROUP BY clausule.
  6. Evalueer HAVING voorwaarden tegen groepen, waarbij groepen worden uitgefilterd die niet overeenkomen.
  7. Sorteer resultaat, volgens ORDER BY clausule.


  1. kopieer gegevens van een mysql-database naar een andere mysql-database met java

  2. Wat is de syntaxis om een ​​Oracle-procedure te definiëren binnen een andere opgeslagen procedure?

  3. trek 1 af van het getal in een rij SQL Query

  4. MySQL Selecteer de beste rondetijden, gegroepeerd op gebruiker