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

Quels SGBD autorisent un tri d'un attribut qui n'est pas présent dans la clause select ?

Votre requête est parfaitement conforme à la syntaxe légale, vous pouvez trier par colonnes qui ne sont pas présentes dans le select.

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 , sub partie 28). Cela confirme que votre requête est conforme à la syntaxe légale.

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.