PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Pourquoi ne puis-je pas exclure des colonnes dépendantes de `GROUP BY` lorsque j'agrège par clé ?

Parce que seul le PK couvre toutes les colonnes d'une table sous-jacente dans le GROUP BY clause. Par conséquent, votre première requête fonctionne. Un UNIQUE la contrainte ne le fait pas.

La combinaison d'un UNIQUE non reportable et un NOT NULL contrainte serait également admissible. Mais ce n'est pas implémenté - ainsi que certaines autres dépendances fonctionnelles connues du standard SQL. Peter Eisentraut, l'auteur principal du long métrage, avait plus en tête, mais il a été déterminé à l'époque que la demande est faible et que les coûts associés pourraient être élevés. Voir la discussion sur la fonctionnalité sur pgsql-hackers.

Le manuel :

Lorsque GROUP BY est présent, ou si des fonctions d'agrégation sont présentes, il n'est pas valide pour le SELECT listes d'expressions pour faire référence à des colonnes non groupées, sauf dans les fonctions d'agrégation ou lorsque la colonne non groupée dépend fonctionnellement des colonnes groupées, car il y aurait autrement plus d'une valeur possible à renvoyer pour une colonne non groupée. Une dépendance fonctionnelle existe si les colonnes groupées (ou un sous-ensemble de celles-ci) sont la clé primaire de la table contenant la colonne non groupée.

Et plus explicitement :

PostgreSQL reconnaît la dépendance fonctionnelle (permettant aux colonnes d'être omises de GROUP BY ) uniquement lorsque la clé primaire d'une table est incluse dans le GROUP BY liste. La norme SQL spécifie des conditions supplémentaires qui doivent être reconnues.

Depuis c.vin est UNIQUE NOT NULL , vous pouvez corriger votre deuxième requête en utilisant à la place la colonne PK :

...
group by c.id;

De plus, bien que l'intégrité référentielle soit appliquée et que toute la table soit interrogée, les deux requêtes données peuvent être considérablement moins chères :agréger les lignes dans appraisal avant la jointure. Cela supprime le besoin de GROUP BY dans le SELECT extérieur a priori. Comme :

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;

Voir :

  • Plusieurs appels array_agg() dans une seule requête

Connexe :

  • L'instruction SQL fonctionnant dans MySQL ne fonctionne pas dans Postgresql - Sum &group_by rails 3
  • PostgreSQL - Clause GROUP BY