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

PostgreSQL - La query secondaria correlata non riesce?

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:

  1. Genera un insieme di righe dalle tabelle, incluse le righe prodotte da JOIN .
  2. Valuta WHERE condizioni rispetto all'insieme di righe, filtrando le righe che non corrispondono.
  3. Calcola le espressioni nell'elenco di selezione per ciascuna nell'insieme di righe.
  4. 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).
  5. Condensare i gruppi in una singola riga per gruppo, secondo GROUP BY clausola.
  6. Valuta HAVING condizioni contro i gruppi, filtrando i gruppi che non corrispondono.
  7. Ordina il risultato in base a ORDER BY clausola.