Alcuni punti importanti sull'utilizzo di SQL:
- Non è possibile utilizzare alias di colonna nella clausola WHERE, ma è possibile nella clausola HAVING. Questa è la causa dell'errore che hai ricevuto.
- Puoi fare il tuo conteggio meglio usando JOIN e GROUP BY che usando sottoquery correlate. Sarà molto più veloce.
- Utilizza la clausola HAVING per filtrare i gruppi.
Ecco come scriverei questa query:
SELECT t1.id, COUNT(t2.id) AS num_things
FROM t1 JOIN t2 USING (id)
GROUP BY t1.id
HAVING num_things = 5;
Mi rendo conto che questa query può saltare il JOIN
con t1, come nella soluzione di Charles Bretana. Ma suppongo che tu possa volere che la query includa alcune altre colonne da t1.
Re:la domanda nel commento:
La differenza è che il WHERE
la clausola viene valutata sulle righe, prima di GROUP BY
riduce i gruppi a una singola riga per gruppo. Il HAVING
la clausola viene valutata dopo la formazione dei gruppi. Quindi non puoi, ad esempio, modificare COUNT()
di un gruppo utilizzando HAVING
; puoi escludere solo il gruppo stesso.
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;
Nella query precedente, WHERE
filtri per le righe che soddisfano una condizione e HAVING
filtri per i gruppi che hanno almeno cinque conteggi.
Il punto che causa confusione alla maggior parte delle persone è quando non hanno un GROUP BY
clausola, quindi sembra come HAVING
e WHERE
sono intercambiabili.
WHERE
viene valutato prima delle espressioni nell'elenco di selezione. Questo potrebbe non essere ovvio perché la sintassi SQL mette prima l'elenco di selezione. Quindi puoi risparmiare un sacco di calcoli costosi usando WHERE
per limitare le righe.
SELECT <expensive expressions>
FROM t1
HAVING primaryKey = 1234;
Se utilizzi una query come quella sopra, le espressioni nell'elenco di selezione vengono calcolate per ogni riga , solo per scartare la maggior parte dei risultati a causa di HAVING
condizione. Tuttavia, la query seguente calcola l'espressione solo per la singola riga corrispondendo a WHERE
condizione.
SELECT <expensive expressions>
FROM t1
WHERE primaryKey = 1234;
Quindi, per ricapitolare, le query vengono eseguite dal motore di database in base a una serie di passaggi:
- Genera un insieme di righe dalle tabelle, incluse le righe prodotte da
JOIN
. - Valuta
WHERE
condizioni rispetto all'insieme di righe, filtrando le righe che non corrispondono. - Calcola le espressioni nell'elenco di selezione per ciascuna nell'insieme di righe.
- Applica alias di colonna (tieni presente che questo è un passaggio separato, il che significa che non puoi utilizzare alias nelle espressioni nell'elenco di selezione).
- Condensare i gruppi in una singola riga per gruppo, secondo
GROUP BY
clausola. - Valuta
HAVING
condizioni contro i gruppi, filtrando i gruppi che non corrispondono. - Ordina il risultato in base a
ORDER BY
clausola.