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

¿Por qué no puedo excluir columnas dependientes de `GROUP BY` cuando agrego por clave?

Porque solo el PK cubre todas las columnas de una tabla subyacente en el GROUP BY cláusula. Por lo tanto, su primera consulta funciona. UN UNIQUE la restricción no lo hace.

La combinación de un UNIQUE no diferible y un NOT NULL la restricción también calificaría. Pero eso no está implementado, así como algunas otras dependencias funcionales conocidas por el estándar SQL. Peter Eisentraut, el autor principal del artículo, tenía más en mente, pero en ese momento se determinó que la demanda es baja y los costos asociados podrían ser altos. Vea la discusión sobre la función en pgsql-hackers.

El manual:

Cuando GROUP BY está presente, o cualquier función agregada está presente, no es válido para SELECT Expresiones de lista para hacer referencia a columnas no agrupadas excepto dentro de funciones agregadas o cuando la columna no agrupada dependa funcionalmente de las columnas agrupadas, ya que de lo contrario habría más de un valor posible para devolver para una columna no agrupada. Existe una dependencia funcional si las columnas agrupadas (o un subconjunto de las mismas) son la clave principal de la tabla que contiene la columna no agrupada.

Y más explícitamente:

PostgreSQL reconoce la dependencia funcional (permitiendo que las columnas se omitan de GROUP BY ) solo cuando la clave principal de una tabla se incluye en GROUP BY lista. El estándar SQL especifica condiciones adicionales que deben reconocerse.

Desde c.vin es UNIQUE NOT NULL , puede corregir su segunda consulta usando la columna PK en su lugar:

...
group by c.id;

Además, si bien se aplica la integridad referencial y se consulta toda la tabla, ambas consultas dadas pueden ser sustancialmente más económicas:filas agregadas en appraisal antes la unión Esto elimina la necesidad de GROUP BY en el exterior SELECT a priori. Me gusta:

SELECT c.vin, c.color, c.brand
     , a.min_appraisal
     , a.max_appraisal
FROM   car c
LEFT   JOIN (
   SELECT car_vin
        , min(price) AS min_appraisal
        , max(price) AS max_appraisal
   FROM   appraisal
   GROUP  BY car_vin
   ) a ON a.car_vin = c.vin;

Ver:

  • Múltiples llamadas a array_agg() en una sola consulta

Relacionado:

  • La declaración SQL que funciona en MySQL no funciona en Postgresql - Sum &group_by rails 3
  • PostgreSQL - Cláusula GROUP BY