sql >> Database teknologi >  >> RDS >> PostgreSQL

PostgreSQL - Korreleret underforespørgsel mislykkedes?

Et par vigtige punkter om brug af SQL:

  • Du kan ikke bruge kolonnealiaser i WHERE-udtrykket, men det kan du i HAVING-udtrykket. Det er årsagen til den fejl, du fik.
  • Du kan gøre din optælling bedre ved at bruge JOIN og GROUP BY end ved at bruge korrelerede underforespørgsler. Det vil være meget hurtigere.
  • Brug HAVING-sætningen til at filtrere grupper.

Sådan ville jeg skrive denne forespørgsel:

SELECT t1.id, COUNT(t2.id) AS num_things
FROM t1 JOIN t2 USING (id)
GROUP BY t1.id
HAVING num_things = 5;

Jeg er klar over, at denne forespørgsel kan springe JOIN over med t1, som i Charles Bretanas løsning. Men jeg antager, at du måske ønsker, at forespørgslen skal inkludere nogle andre kolonner fra t1.

Re:spørgsmålet i kommentaren:

Forskellen er, at WHERE klausul evalueres på rækker før GROUP BY reducerer grupper til en enkelt række pr. gruppe. HAVING klausul evalueres efter grupper er dannet. Så du kan for eksempel ikke ændre COUNT() af en gruppe ved at bruge HAVING; du kan kun ekskludere selve gruppen.

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;

I ovenstående forespørgsel, WHERE filtre for rækker, der matcher en betingelse, og HAVING filtre for grupper, der har mindst fem tæller.

Det punkt, der forårsager forvirring hos de fleste, er, når de ikke har en GROUP BY klausul, så det ser ud som HAVING og WHERE er udskiftelige.

WHERE evalueres før udtryk i valglisten. Dette er muligvis ikke indlysende, fordi SQL-syntaks sætter valglisten først. Så du kan spare en masse dyr beregning ved at bruge WHERE for at begrænse rækker.

SELECT <expensive expressions>
FROM t1
HAVING primaryKey = 1234;

Hvis du bruger en forespørgsel som ovenstående, beregnes udtrykkene i valglisten for hver række , kun for at kassere de fleste resultater på grund af HAVING tilstand. Forespørgslen nedenfor beregner dog kun udtrykket for enkelt række matcher WHERE tilstand.

SELECT <expensive expressions>
FROM t1
WHERE primaryKey = 1234;

Så for at opsummere, køres forespørgsler af databasemotoren i henhold til en række trin:

  1. Generer sæt rækker fra tabeller, inklusive alle rækker, der er produceret af JOIN .
  2. Vurder WHERE betingelser i forhold til sættet af rækker, frafiltrering af rækker, der ikke matcher.
  3. Beregn udtryk i valglisten for hver i rækken.
  4. Anvend kolonnealiasser (bemærk, at dette er et separat trin, hvilket betyder, at du ikke kan bruge aliaser i udtryk i valglisten).
  5. Kondenser grupper til en enkelt række pr. gruppe i henhold til GROUP BY klausul.
  6. Vurder HAVING betingelser mod grupper, frafiltrering af grupper, der ikke matcher.
  7. Sortér resultatet i henhold til ORDER BY klausul.


  1. Kortslutningslogiske evalueringsoperatører

  2. Hvordan ser Alter Table-syntaksen ud for at tilføje en DATETIME-kolonne?

  3. Guide til design af database til sociale netværkssystem i MySQL

  4. skrive tabeller til Postgresql ved hjælp af rPostgreSQL, når databasenavnet kun består af store bogstaver