PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Por que não posso excluir colunas dependentes de `GROUP BY` quando agrego por uma chave?


Porque apenas o PK cobre todas as colunas de uma tabela subjacente no GROUP BY cláusula. Portanto, sua primeira consulta funciona. Um UNIQUE restrição não.

A combinação de um UNIQUE não adiável e um NOT NULL restrição também se qualificaria. Mas isso não é implementado - assim como algumas outras dependências funcionais conhecidas pelo padrão SQL. Peter Eisentraut, o principal autor do recurso, tinha mais em mente, mas foi determinado na época que a demanda é baixa e os custos associados podem ser altos. Veja a discussão sobre o recurso em pgsql-hackers.

O manual:

Quando GROUP BY está presente, ou qualquer função agregada está presente, não é válido para o SELECT list expressões para se referir a colunas desagrupadas, exceto dentro de funções agregadas ou quando a coluna desagrupada for funcionalmente dependente das colunas agrupadas, pois, caso contrário, haveria mais de um valor possível a ser retornado para uma coluna desagrupada. Existe uma dependência funcional se as colunas agrupadas (ou um subconjunto delas) forem a chave primária da tabela que contém a coluna desagrupada.

E mais explicitamente:

O PostgreSQL reconhece a dependência funcional (permitindo que as colunas sejam omitidas de GROUP BY ) somente quando a chave primária de uma tabela estiver incluída no GROUP BY Lista. O padrão SQL especifica condições adicionais que devem ser reconhecidas.

Desde c.vin é UNIQUE NOT NULL , você pode corrigir sua segunda consulta usando a coluna PK:
...
group by c.id;

Além disso, embora a integridade referencial seja aplicada e toda a tabela seja consultada, ambas as consultas fornecidas podem ser substancialmente mais baratas:agregar linhas em appraisal antes a junção. Isso elimina a necessidade de GROUP BY no SELECT externo a priori. Como:
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:
  • Várias chamadas array_agg() em uma única consulta

Relacionado:
  • Instrução SQL funcionando no MySQL não funcionando no Postgresql - Sum &group_by rails 3
  • PostgreSQL - cláusula GROUP BY