sql >> Base de Datos >  >> RDS >> PostgreSQL

Postgres LEFT JOIN con SUM, faltan registros

Por lo general, es más rápido si obtiene todas o la mayoría de las filas :

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;

Los índices son irrelevantes aquí, los escaneos completos de la tabla serán más rápidos. Excepto si las mascotas vivas son raras caso, entonces un índice parcial debería ayudar. Me gusta:

CREATE INDEX pets_alive_idx ON pets (person_id, kind) WHERE alive;

Incluí todas las columnas necesarias para la consulta (person_id, kind) para permitir exploraciones de solo índice.

SQL Fiddle.

Por lo general, el más rápido para un pequeño subconjunto o una sola fila :

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;

Debería tener al menos un índice en pets.person_id para esto (o el índice parcial de arriba) - y posiblemente más, dependiendo del WHERE condición.

Respuestas relacionadas: