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

Ottieni il conteggio delle righe dopo GROUP BY

Se il tuo progetto impone l'integrità referenziale, non devi unirti alla tabella residences assolutamente per questo scopo. Assumendo anche un UNIQUE o PK vincolo su (residence_id, amenity_id) (altrimenti hai bisogno di query diverse!)

La query migliore dipende da ciò di cui hai bisogno esattamente .

Utilizzando una funzione finestra, puoi anche farlo in un unico livello di query:

SELECT count(*) OVER () AS ct
FROM   listed_amenities
WHERE  amenity_id IN (48, 49, 50)
GROUP  BY residence_id
HAVING count(*) = 3
LIMIT  1;

Questa funzione della finestra aggiunge il conteggio totale a ogni riga senza aggregare le righe. Considera la sequenza di eventi in un SELECT domanda:

Di conseguenza, potresti utilizzare una query simile per restituire tutti gli ID idonei (o anche intere righe) e aggiungere il conteggio a ogni riga (in modo ridondante):

SELECT residence_id, count(*) OVER () AS ct
FROM   listed_amenities
WHERE  amenity_id IN (48, 49, 50)
GROUP  BY residence_id
HAVING count(*) = 3;

Ma è meglio usare una sottoquery, che è in genere molto più economica :

SELECT count(*) AS ct
FROM  (
   SELECT 1
   FROM   listed_amenities
   WHERE  amenity_id IN (48, 49, 50)
   GROUP  BY residence_id 
   HAVING count(*) = 3
   ) sub;

Potresti restituisce una matrice di ID (al contrario di set sopra) allo stesso tempo, a quasi nessun costo aggiuntivo:

SELECT array_agg(residence_id ) AS ids, count(*) AS ct
FROM  (
   SELECT residence_id 
   FROM   listed_amenities
   WHERE  amenity_id IN (48, 49, 50)
   GROUP  BY residence_id
   HAVING count(*) = 3
   ) sub;

Ci sono molte altre varianti, dovresti chiarire il risultato atteso. Come questo:

SELECT count(*) AS ct
FROM   listed_amenities l1
JOIN   listed_amenities l2 USING (residence_id)
JOIN   listed_amenities l3 USING (residence_id)
WHERE  l1.amenity_id = 48
AND    l2.amenity_id = 49
AND    l2.amenity_id = 50;

Fondamentalmente è un caso di divisione relazionale. Abbiamo raccolto un arsenale di tecniche qui: