PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Ruft die Anzahl der Zeilen nach GROUP BY ab

Wenn Ihr Design referentielle Integrität erzwingt, müssen Sie der Tabelle residences nicht beitreten überhaupt zu diesem Zweck. Auch unter der Annahme eines UNIQUE oder PK Beschränkung auf (residence_id, amenity_id) (Andernfalls benötigen Sie andere Abfragen!)

Die beste Abfrage hängt davon ab, was Sie genau benötigen .

Mit einer Fensterfunktion können Sie das können tun Sie dies sogar auf einer einzigen Abfrageebene:

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

Diese Fensterfunktion hängt die Gesamtzahl an jede Zeile an, ohne Zeilen zu aggregieren. Betrachten Sie die Abfolge von Ereignissen in einem SELECT Abfrage:

Dementsprechend könnten Sie eine ähnliche Abfrage verwenden, um alle qualifizierenden IDs (oder sogar ganze Zeilen) zurückzugeben und die Anzahl an jede Zeile (redundant) anzuhängen:

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

Aber verwenden Sie besser eine Unterabfrage, das ist in der Regel viel billiger :

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;

Sie könnten gibt ein Array von IDs zurück (im Gegensatz zum set oben) gleichzeitig für kaum mehr Kosten:

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;

Es gibt noch viele andere Varianten, man müsste das erwartete Ergebnis abklären. Wie dieses hier:

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;

Im Grunde ist es ein Fall von relationaler Teilung. Wir haben hier ein Arsenal an Techniken zusammengestellt: