Gibt SELECT ROW_NUMBER () garantiert Ergebnisse zurück, die nach den generierten Zeilennummern sortiert sind?

10

Betrachten Sie beispielsweise die SQL-Abfrage:

SELECT
   A.[Name],
   ROW_NUMBER() OVER(ORDER BY A.[Name] ASC)
FROM
   [FooTable] AS A

Hier beobachte ich die zurückgegebenen Ergebnisse sortiert nach A. [Name]. Wenn ich die in der Funktion ROW_NUMBER definierte Sortierspalte in eine andere Spalte ändere, werden die Ergebnisse erneut nach dieser Spalte sortiert.

Ich hatte erwartet, dass die Zeilennummer den Zeilen zugewiesen wird, aber ich hatte nicht erwartet, dass die Zeilen nach denselben Kriterien sortiert zurückkommen. Ist dies lediglich ein Nebeneffekt der Ausführung der Abfrage (in meinem Fall unter SQL Server 2008 R2) oder ist dieses Verhalten garantiert? (Ich konnte keinen Hinweis auf eine solche Garantie finden).

Redcalx
quelle
10
Es gibt niemals eine Garantie. Je. Sofern Sie SQL Server nicht mitteilen, wie etwas bestellt werden soll, können Sie die Daten in der gewünschten Reihenfolge zurückgeben. Wenn Sie die Bestellung bis weglassen, teilen Sie SQL Server mit, dass Ihnen die Bestellung egal ist. Wenn Sie eine Garantie wünschen, geben Sie einfach die ORDER BY-Klausel bereits ein.
Aaron Bertrand
Es gibt einen guten Grund zu fragen, da die fragliche Order-by-Klausel sehr komplex ist und das Kopieren daher sowohl Code-Wartungsballast als auch die Wahrscheinlichkeit zukünftiger Fehler erhöht. Die andere Alternative ist ein geringfügiges Refactoring, das ich möglicherweise vermeiden könnte, wenn der SQL-Standard eine implizite Sortierreihenfolge definiert. Auf jeden Fall war ich nur interessiert, ob es formelle Unterlagen zu diesem Punkt gab.
Redcalx
1
Warum also nicht diese Frage stellen?
Aaron Bertrand

Antworten:

14

Wenn Sie die Frage gestellt hätten, hätten Sie sie eigentlich stellen wollen:

Wie kann ich bestellen, ROW_NUMBER()ohne den komplexen ORDER BYAusdruck zu wiederholen ?

Wir hätten Ihnen sagen können, dass Sie einen Alias ​​für den ROW_NUMBER()Ausdruck erstellen und dann nach dem Alias ​​sortieren sollen:

SELECT
   A.[Name],
   rn = ROW_NUMBER() OVER (ORDER BY <complex expression>)
FROM
   dbo.[FooTable] AS A
ORDER BY rn;

Jetzt müssen Sie den Ausdruck nur noch an einer Stelle ändern, und die resultierende Sortierung basiert auf diesem Ausdruck, ohne ihn wiederholen zu müssen.

Aaron Bertrand
quelle
6
Tatsächlich repeating the complex ORDER BY expressionwird nicht einmal garantiert, dass die Ausgabe in der Reihenfolge ROW_NUMBER () ausgegeben wird. Es sei denn, die Spalten in der ORDER BY-Klausel bilden einen eindeutigen Schlüssel.
24.
22

Absolut nicht. Beweis:

SELECT
   A.[Name],
   ROW_NUMBER() OVER(ORDER BY A.[Name] ASC),
   ROW_NUMBER() OVER(ORDER BY A.[Name] DESC)
FROM
   [FooTable] AS A

Die einzige Möglichkeit, eine Bestellung in SQL zu garantieren, besteht darin, sie anzufordern und für ORDER BYdas Ergebnis selbst zu verwenden.

Remus Rusanu
quelle
OK, ich werde eine weitere Qualifikation hinzufügen - werden die Ergebnisse garantiert sortiert, wenn nur eine ROW_NUMBER () -Klausel angegeben wird.
Redcalx
22
Die einzige Möglichkeit, eine Bestellung in SQL zu garantieren, besteht darin, danach zu fragen
Remus Rusanu
0

Tatsächlich könnte die (alte) Frage erweitert werden, um auch die Partition nach Teilen einzuschließen , da es eine implizite Reihenfolge von zuerst der Partition nach und dann der Reihenfolge nach Teilen zu geben scheint.

Es ist also nicht ganz so einfach, wie einige vorgeschlagen haben, die Zeilennummer zuzuweisen und diese für die Bestellung zu verwenden.

Wir würden eine verschachtelte SQL benötigen, um die Partition auch durch Klausel zu extrahieren (wenn wir sie natürlich nicht einfach wiederholen wollen)

Empirisch scheinen wir implizit die letzte Ordnungszeile zu bekommen

Select
  <field-list>, 
  rn=Row_Number() over(partition by <PartionClause>) order by <OrderClause>
from ....
Order by <PartionClause> asc, rn asc

Was uns jedoch fehlt, ist ein Beweis oder eine Garantie dafür, dass es immer gilt.

(Wenn mehrere Row_Number () -Aufrufe im Spiel sind, scheint der LETZTE die Reihenfolge anzugeben.)

BEACHTEN SIE AUCH, wenn Sie die Bestellung explizit durch den Ausführungsplan hinzufügen , wird ein letzter Sortierschritt deutlich angezeigt, und das Sortieren eines bereits sortierten Satzes ist der schlimmste Fall, daher dauert es mit der Bestellung nach wesentlich länger als ohne

Eske Rahn
quelle
1
Dies beantwortet die Frage nicht wirklich und scheint sowohl mit der akzeptierten Antwort als auch mit einer hoch bewerteten Antwort nicht übereinzustimmen.
Erik Darling
Ich stimme zu, dass meine eher ein Kommentar als eine Antwort ist. Nun, die akzeptierte Antwort ist nicht wirklich eine Antwort, außer dass wir der Bestellung besser nicht vertrauen sollten - und genau das war die Frage. Aus dem Ausführungsplan ist ersichtlich, dass tatsächlich eine Sortierung durchgeführt wird, und wenn wir eine explizite Reihenfolge nach hinzufügen, erhalten wir eine zweite Sortierung. Aber das ist KEIN Beweis, es ist nur ein Teil des empirischen Wissens
Eske Rahn
(Natürlich werden die Sortierungen nur durchgeführt, wenn es keinen geeigneten Index gibt, mit dem auf die Tabelle zugegriffen werden kann, sondern nur hinzugefügt, um zu zeigen, dass es im Allgemeinen nicht kostenlos ist, die Bestellung explizit zu erteilen.)
Eske Rahn