Meestal het snelst als u alle of de meeste rijen ophaalt :
SELECT pp.id
, COALESCE(pt.a_dog_ct, 0) AS alive_dogs_count
, COALESCE(pt.a_cat_ct, 0) AS alive_cats_count
FROM people pp
LEFT JOIN (
SELECT person_id
, count(kind = 'dog' OR NULL) AS a_dog_ct
, count(kind = 'cat' OR NULL) AS a_cat_ct
FROM pets
WHERE alive
GROUP BY 1
) pt ON pt.person_id = pp.id;
Indexen zijn hier niet relevant, volledige tabelscans zijn het snelst. Behalve als levende huisdieren zeldzaam zijn geval, dan een gedeeltelijke index zou moeten helpen. Vind ik leuk:
CREATE INDEX pets_alive_idx ON pets (person_id, kind) WHERE alive;
Ik heb alle kolommen opgenomen die nodig zijn voor de zoekopdracht (person_id, kind)
om alleen-index scans toe te staan.
Meestal het snelst voor een kleine subset of een enkele rij :
SELECT pp.id
, count(kind = 'dog' OR NULL) AS alive_dogs_count
, count(kind = 'cat' OR NULL) AS alive_cats_count
FROM people pp
LEFT JOIN pets pt ON pt.person_id = pp.id
AND pt.alive
WHERE <some condition to retrieve a small subset>
GROUP BY 1;
Je moet op zijn minst een index hebben op pets.person_id
hiervoor (of de gedeeltelijke index van hierboven) - en mogelijk meer, afhankelijk van de WHERE
staat.
Gerelateerde antwoorden:
- Query met LEFT JOIN retourneert geen rijen voor telling van 0
- GROUP of DISTINCT na JOIN retourneert duplicaten
- Get count van een externe sleutel uit meerdere tabellen