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 leSELECT
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 leGROUP 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