Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Welche DBMS erlauben eine Sortierung nach einem Attribut, das nicht in der Select-Klausel vorhanden ist?

Ihre Abfrage ist eine vollkommen legale Syntax, Sie können nach Spalten sortieren, die nicht in der Auswahl vorhanden sind.

Wenn Sie die vollständigen Spezifikationen zur legalen Reihenfolge benötigen, finden Sie im SQL Standard 2003 eine lange Liste von Anweisungen darüber, was die Reihenfolge enthalten sollte und was nicht (02-Foundation, Seite 415, Abschnitt 7.13 , sub Teil 28). Dies bestätigt, dass Ihre Anfrage eine legale Syntax hat.

Ich denke, Ihre Verwirrung könnte durch das Auswählen und / oder Sortieren nach Spalten entstehen, die nicht in der Gruppe vorhanden sind, oder durch das Sortieren nach Spalten, die nicht in der Auswahl enthalten sind, wenn Sie unterschiedliche verwenden.

Beide haben das gleiche grundlegende Problem, und MySQL ist meines Wissens das einzige, das beides zulässt.

Das Problem besteht darin, dass bei der Verwendung von group by oder distink alle Spalten, die nicht in beiden enthalten sind, nicht benötigt werden, sodass es keine Rolle spielt, ob sie mehrere unterschiedliche Werte in den Zeilen haben, da sie nie benötigt werden. Stellen Sie sich diesen einfachen Datensatz vor:

ID  | Column1 | Column2  |
----|---------+----------|
1   |    A    |    X     |
2   |    A    |    Z     |
3   |    B    |    Y     |

Wenn Sie schreiben:

SELECT  DISTINCT Column1
FROM    T;

Sie würden bekommen

 Column1 
---------
     A   
     B   

Wenn Sie dann ORDER BY Column2 hinzufügen , welche der beiden Spalte2 würden Sie verwenden, um A nach, X oder Z zu ordnen? Es ist nicht deterministisch, wie ein Wert für Spalte2 ausgewählt wird.

Dasselbe gilt für die Auswahl von Spalten, die nicht in Gruppieren nach enthalten sind. Stellen Sie sich der Einfachheit halber die ersten beiden Zeilen der vorherigen Tabelle vor:

ID  | Column1 | Column2  |
----|---------+----------|
1   |    A    |    X     |
2   |    A    |    Z     |

In MySQL können Sie schreiben

SELECT  ID, Column1, Column2
FROM    T
GROUP BY Column1;

Dies bricht eigentlich den SQL-Standard, aber es funktioniert in MySQL, aber das Problem ist, dass es nicht deterministisch ist, das Ergebnis:

ID  | Column1 | Column2  |
----|---------+----------|
1   |    A    |    X     |

Ist nicht mehr oder weniger richtig als

ID  | Column1 | Column2  |  
----|---------+----------|
2   |    A    |    Y     |

Was Sie also sagen, ist, mir eine Zeile für jeden unterschiedlichen Wert von Column1 zu geben , die beide Ergebnismengen erfüllen, woher wissen Sie also, welche Sie erhalten werden? Nun, Sie tun es nicht, es scheint ein ziemlich weit verbreitetes Missverständnis zu sein, dass Sie hinzufügen und ORDER BY können -Klausel, um die Ergebnisse zu beeinflussen, also zum Beispiel die folgende Abfrage:

SELECT  ID, Column1, Column2
FROM    T
GROUP BY Column1
ORDER BY ID DESC;

Würde sicherstellen, dass Sie das folgende Ergebnis erhalten:

ID  | Column1 | Column2  |  
----|---------+----------|
2   |    A    |    Y     |

wegen der ORDER BY ID DESC , jedoch ist dies nicht wahr (wie hier gezeigt ). ).

Die MySQL-Dokumente Zustand:

Obwohl Sie also eine Reihenfolge haben, gilt dies erst, nachdem eine Zeile pro Gruppe ausgewählt wurde, und diese eine Zeile ist nicht deterministisch.

Der SQL-Standard erlaubt zwar Spalten in der Auswahlliste, die nicht im GROUP BY oder einer Aggregatfunktion enthalten sind, jedoch müssen diese Spalten funktional von einer Spalte im GROUP BY abhängig sein. Aus dem SQL-2003-Standard (5WD-02-Foundation-2003-09 - Seite 346) - http ://www.wiscorp.com/sql_2003_standard.zip

Beispielsweise ist die ID in der Beispieltabelle der PRIMARY KEY, daher wissen wir, dass er in der Tabelle eindeutig ist, sodass die folgende Abfrage dem SQL-Standard entspricht und in MySQL ausgeführt wird und derzeit in vielen DBMS fehlschlägt (zum Zeitpunkt des Schreibens von Postgresql ist das DBMS, das ich kenne, um den Standard korrekt zu implementieren - Beispiel hier ):

SELECT  ID, Column1, Column2
FROM    T
GROUP BY ID;

Da die ID für jede Zeile eindeutig ist, kann es nur einen Wert von Column1 geben für jede ID ein Wert von Column2 Es besteht keine Unklarheit darüber, was für jede Zeile zurückgegeben werden soll.