Toute colonne de la clause GROUP BY doit désigner une colonne présente dans la clause SELECT :
soit comme attribut d'agrégation,
soit comme attribut présent dans une fonction d'agrégation.
SELECT countrycode, citycode, COUNT(citycode)
FROM city
GROUP BY countrycode;
ERROR: column "city.citycode" must appear in the GROUP BY clause or be used in an aggregate function;
SELECT citycode, countrycode, AVG(population)
FROM city
GROUP BY citycode;
citycode | countrycode | avg
----------+-------------+------------------------
LLL | FR | 0.20000000000000000000
BAR | ES | 1.90000000000000000000
PAR | FR | 2.2000000000000000
LYO | FR | 0.50000000000000000000
ZAR | ES | 0.70000000000000000000
AMN | FR | 0.10000000000000000000
MAD | ES | 3.3000000000000000
La requête est non standard, même si c'est logiquement acceptable, car il n'y a qu'un countrycode par citycode ici, city étant une clé.
Certains SGBD comme Postgres acceptent donc cette syntaxe, en ajoutant implicitement l'attribut qui manque au GROUP BY, car il n'y a pas d’ambiguïté si l'on analyse le graphe des DF : citycode → countrycode. Mais le standard impose d'être explicite, car le SGBD a le droit de ne pas le deviner.
SELECT ci.countrycode, co.name, count(*)
FROM city ci JOIN country co
ON ci.countrycode=co.countrycode
GROUP BY ci.countrycode, co.name;
countrycode | name | count
-------------+--------+-------
FR | France | 4
ES | Spain | 3
SELECT co.countrycode, co.name, count(*)
FROM city ci JOIN country co
ON ci.countrycode=co.countrycode
GROUP BY co.countrycode;
La requête est non standard, car co.name est dans le SELECT mais pas dans le GROUP BY. Comme dans l'exemple précédent certains SGBD accepteront cette requête grâce à la DF évidente : co.countrycode → co.name
Mais si l'on utilise à présent ci.countrycode à la place de co.countrycode...
SELECT ci.countrycode, co.name, count(*)
FROM city ci JOIN country co
ON ci.countrycode=co.countrycode
GROUP BY ci.countrycode;
ERROR: column "co.name" must appear in the GROUP BY clause or be used in an aggregate function
La requête est non standard, co.name doit être mentionné dans la clause GROUP BY. Logiquement on pourrait juger cela superflu, car par transitivité ci.countrycode → co.name, mais le SGBD (ici Postgres) ne va pas jusque là.
Il est donc conseillé d'appliquer le Single-Value Rule et de toujours expliciter tous les attributs dans le GROUP BY, pour éviter la dépendance au SGBD ou bien les erreurs liées à des variations mineures de syntaxe.