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