Zwykle najszybciej, jeśli pobierzesz wszystkie lub większość wierszy :
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;
Indeksy nie mają tu znaczenia, skanowanie pełnej tabeli będzie najszybsze. Z wyjątkiem jeśli żywe zwierzęta są rzadkie przypadku, a następnie częściowy indeks powinno pomóc. Na przykład:
CREATE INDEX pets_alive_idx ON pets (person_id, kind) WHERE alive;
Uwzględniłem wszystkie kolumny potrzebne do zapytania (person_id, kind)
aby zezwolić na skanowanie tylko do indeksu.
Zwykle najszybszy w przypadku małego podzbioru lub pojedynczego wiersza :
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;
Powinieneś mieć przynajmniej indeks na pets.person_id
dla tego (lub częściowego indeksu z góry) - i ewentualnie więcej, w zależności od WHERE
stan.
Powiązane odpowiedzi:
- Zapytanie z LEFT JOIN nie zwraca wierszy dla liczby 0
- GROUP lub DISTINCT po JOIN zwraca duplikaty
- Pobierz liczbę klucza obcego z wielu tabel