Votre requête est parfaitement conforme à la syntaxe légale, vous pouvez trier par colonnes qui ne sont pas présentes dans le select.
- Démo de travail avec MySQL
- Démo de travail avec SQL Server
- Démo de travail avec Postgresql
- Démo de travail avec SQLite
- Démo de travail avec Oracle
Si vous avez besoin des spécifications complètes sur l'ordre légal, le SQL Standard 2003 contient une longue liste d'instructions sur ce que l'ordre doit contenir et ne doit pas contenir, (02-Foundation, page 415, section 7.13
Je pense que votre confusion pourrait provenir de la sélection et/ou de la commande par colonnes non présentes dans le groupe par, ou de la commande par colonnes non présentes dans la sélection lors de l'utilisation de distinct.
Les deux ont le même problème fondamental, et MySQL est le seul à ma connaissance qui permet l'un ou l'autre.
Le problème est que lors de l'utilisation de group by ou distinct, toutes les colonnes non contenues dans l'une ou l'autre ne sont pas nécessaires, donc peu importe si elles ont plusieurs valeurs différentes sur les lignes car elles ne sont jamais nécessaires. Imaginez cet ensemble de données simple :
ID | Column1 | Column2 |
----|---------+----------|
1 | A | X |
2 | A | Z |
3 | B | Y |
Si vous écrivez :
SELECT DISTINCT Column1
FROM T;
Vous obtiendriez
Column1
---------
A
B
Si vous ajoutez ensuite ORDER BY Column2
, laquelle des deux colonnes2 utiliseriez-vous pour ordonner A par, X ou Z ? Il n'est pas déterministe quant à la façon de choisir une valeur pour la colonne2.
Il en va de même pour la sélection de colonnes qui ne sont pas dans le groupe par. Pour simplifier, imaginez les deux premières lignes du tableau précédent :
ID | Column1 | Column2 |
----|---------+----------|
1 | A | X |
2 | A | Z |
Dans MySQL, vous pouvez écrire
SELECT ID, Column1, Column2
FROM T
GROUP BY Column1;
Cela enfreint en fait le standard SQL, mais cela fonctionne dans MySQL, mais le problème est qu'il n'est pas déterministe, le résultat :
ID | Column1 | Column2 |
----|---------+----------|
1 | A | X |
N'est ni plus ni moins correct que
ID | Column1 | Column2 |
----|---------+----------|
2 | A | Y |
Donc, ce que vous dites, c'est me donner une ligne pour chaque valeur distincte de Column1
, que les deux ensembles de résultats satisfont, alors comment savez-vous lequel vous obtiendrez ? Eh bien, vous ne le faites pas, il semble que ce soit une idée fausse assez populaire selon laquelle vous pouvez ajouter et ORDER BY
clause pour influencer les résultats, donc par exemple la requête suivante :
SELECT ID, Column1, Column2
FROM T
GROUP BY Column1
ORDER BY ID DESC;
Assurez-vous d'obtenir le résultat suivant :
ID | Column1 | Column2 |
----|---------+----------|
2 | A | Y |
à cause du ORDER BY ID DESC
, cependant ce n'est pas vrai (comme démontré ici
).
Les documents MySQL état :
Ainsi, même si vous avez une commande par cela, cela ne s'applique qu'après qu'une ligne par groupe a été sélectionnée, et cette ligne n'est pas déterministe.
Le SQL-Standard autorise les colonnes de la liste de sélection qui ne sont pas contenues dans GROUP BY ou une fonction d'agrégation, mais ces colonnes doivent être fonctionnellement dépendantes d'une colonne dans GROUP BY. De la norme SQL-2003 (5WD-02-Foundation-2003-09 - page 346) - http ://www.wiscorp.com/sql_2003_standard.zip
Par exemple, l'ID dans l'exemple de table est la PRIMARY KEY, donc nous savons qu'il est unique dans la table, donc la requête suivante est conforme à la norme SQL et s'exécuterait dans MySQL et échouerait dans de nombreux SGBD actuellement (au moment de la rédaction de Postgresql est le SGBD le plus proche que je connaisse pour implémenter correctement la norme - Exemple ici ):
SELECT ID, Column1, Column2
FROM T
GROUP BY ID;
Étant donné que l'ID est unique pour chaque ligne, il ne peut y avoir qu'une seule valeur de Column1
pour chaque ID, une valeur de Column2
il n'y a aucune ambiguïté sur ce qu'il faut renvoyer pour chaque ligne.