sql >> Databasteknik >  >> RDS >> PostgreSQL

PostgreSQL - Korrelerad underfråga misslyckades?

Några viktiga punkter om att använda SQL:

  • Du kan inte använda kolumnalias i WHERE-satsen, men du kan i HAVING-satsen. Det är orsaken till felet du fick.
  • Du kan räkna bättre genom att använda JOIN och GROUP BY än genom att använda korrelerade underfrågor. Det kommer att gå mycket snabbare.
  • Använd HAVING-satsen för att filtrera grupper.

Så här skulle jag skriva den här frågan:

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

Jag inser att den här frågan kan hoppa över JOIN med t1, som i Charles Bretanas lösning. Men jag antar att du kanske vill att frågan ska inkludera några andra kolumner från t1.

Re:frågan i kommentaren:

Skillnaden är att WHERE satsen utvärderas på rader, före GROUP BY reducerar grupper till en enda rad per grupp. HAVING klausul utvärderas efter att grupper har bildats. Så du kan till exempel inte ändra COUNT() för en grupp genom att använda HAVING; du kan bara exkludera själva 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 ovanstående fråga, WHERE filter för rader som matchar ett villkor och HAVING filter för grupper som har minst fem antal.

Punkten som orsakar förvirring hos de flesta är när de inte har en GROUP BY klausul, så verkar som HAVING och WHERE är utbytbara.

WHERE utvärderas före uttryck i urvalslistan. Detta kanske inte är uppenbart eftersom SQL-syntaxen sätter urvalslistan först. Så du kan spara mycket dyr beräkning genom att använda WHERE för att begränsa rader.

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

Om du använder en fråga som ovan, beräknas uttrycken i urvalslistan för varje rad , bara för att kassera de flesta av resultaten på grund av HAVING skick. Frågan nedan beräknar dock uttrycket endast för den enkla raden matchar WHERE skick.

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

Så för att sammanfatta körs frågor av databasmotorn enligt en rad steg:

  1. Generera uppsättning rader från tabell(er), inklusive alla rader som produceras av JOIN .
  2. Utvärdera WHERE villkor mot uppsättningen rader, filtrerar bort rader som inte matchar.
  3. Räkna uttryck i urvalslistan för var och en i raduppsättningen.
  4. Använd kolumnalias (observera att detta är ett separat steg, vilket innebär att du inte kan använda alias i uttryck i urvalslistan).
  5. Kondensera grupper till en enda rad per grupp, enligt GROUP BY klausul.
  6. Utvärdera HAVING villkor mot grupper, filtrerar bort grupper som inte matchar.
  7. Sortera resultat enligt ORDER BY klausul.


  1. Installera flera MySQL-instanser på en Linux-server - använd en separat MySQL-konfigurationsfil

  2. Finns det något sätt att ge en underfråga ett alias i Oracle 11g SQL?

  3. MySQL-frågor till flerdimensionell php-array

  4. Använda OpenVPN för att säkra åtkomst till ditt databaskluster i molnet