Czy funkcja SELECT ROW_NUMBER () zwraca wyniki posortowane według wygenerowanych numerów wierszy?

10

Np. Rozważ zapytanie SQL:

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

Tutaj obserwuję zwracane wyniki posortowane według A. [Nazwa]. Jeśli zmienię kolumnę sortowania zdefiniowaną w funkcji ROW_NUMBER na inną kolumnę, wyniki zostaną posortowane według tej kolumny.

Oczekiwałem, że numer wiersza zostanie przypisany do wierszy, ale nie spodziewałem się, że wiersze wrócą posortowane według tych samych kryteriów. Czy jest to po prostu efekt uboczny wykonywania zapytania (w moim przypadku na SQL Server 2008 R2) czy to zachowanie jest gwarantowane? (Nie mogłem znaleźć odniesienia do takiej gwarancji).

redcalx
źródło
10
Nigdy nie ma żadnej gwarancji. Zawsze. O ile nie powiesz SQL Serverowi, jak coś zamówić, możesz zwrócić dane w dowolnej kolejności. Pomijając zamówienie, mówisz SQL Server, że nie obchodzi cię zamówienie. Jeśli chcesz mieć gwarancję, po prostu wpisz już klauzulę ORDER BY.
Aaron Bertrand
Istnieje dobry powód, aby pytać, ponieważ rozpatrywana klauzula sortowania według jest bardzo złożona, dlatego kopiowanie stwarza zarówno balast utrzymania kodu, jak i zwiększa prawdopodobieństwo przyszłych defektów. Inną alternatywą jest niewielkie refaktoryzowanie, które, jak sądzę, mogłoby być w stanie uniknąć, gdyby standard SQL zdefiniował domyślną kolejność sortowania. W każdym razie byłem po prostu zainteresowany, czy istnieje formalna dokumentacja obejmująca ten punkt.
redcalx
1
więc dlaczego nie zadać tego pytania?
Aaron Bertrand

Odpowiedzi:

14

Jeśli zadałeś pytanie, myślę, że naprawdę chciałeś zadać:

Jak złożyć zamówienie ROW_NUMBER()bez powtarzania złożonego ORDER BYwyrażenia?

Moglibyśmy poprosić cię o utworzenie aliasu dla ROW_NUMBER()wyrażenia, a następnie sortowanie za pomocą aliasu:

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

Teraz musisz zmienić wyrażenie tylko w jednym miejscu, a wynikowy sort będzie oparty na tym wyrażeniu bez konieczności jego powtarzania.

Aaron Bertrand
źródło
6
W rzeczywistości repeating the complex ORDER BY expressionnawet nie gwarantuje, że dane wyjściowe zostaną wyświetlone według kolejności ROW_NUMBER (). Chyba że kolumny w klauzuli ORDER BY tworzą unikalny klucz.
孔夫子
22

Absolutnie nie. Dowód:

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

Jedynym sposobem na zagwarantowanie zamówienia w SQL jest poproszenie o niego, użycie go ORDER BYna samym wyniku.

Remus Rusanu
źródło
OK Dodam jeszcze jedną kwalifikację - czy wyniki są sortowane, jeśli podano tylko jedną klauzulę ROW_NUMBER ().
redcalx,
22
Jedynym sposobem na zagwarantowanie zamówienia w SQL jest poproszenie o niego
Remus Rusanu,
0

W rzeczywistości (stare) pytanie można rozszerzyć, aby obejmowało również podział według części, ponieważ wydaje się, że istnieje domyślna kolejność według najpierw podziału według, a następnie kolejności według części

Nie jest więc tak proste, jak niektórzy sugerowali, aby przypisać numer_wiersza i użyć go do zamówienia.

Potrzebowalibyśmy również zagnieżdżonego narzędzia sql do wyodrębnienia partycji według klauzuli (jeśli oczywiście nie chcemy tego po prostu powtarzać)

Wydaje się, że empirycznie otrzymujemy ostatnią linię uporządkowania pośrednio

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

Ale brakuje nam jakiegokolwiek dowodu lub gwarancji, że zawsze tak jest.

(Jeśli w grze występuje wiele wywołań Row_Number (), to OSTATNIE wydaje się, że wydaje polecenie)

RÓWNIEŻ UWAGA: jeśli jawnie dodasz zamówienie według planu wykonania, wyraźnie pokazuje ostatni krok sortowania, a sortowanie już posortowanego zestawu jest swego rodzaju najgorszym przypadkiem, dlatego zajmuje to znacznie dłużej w przypadku zamówienia przez niż niż bez

Eske Rahn
źródło
1
To tak naprawdę nie odpowiada na pytanie i wydaje się, że nie zgadza się zarówno z zaakceptowaną odpowiedzią, jak i bardzo pozytywną odpowiedzią.
Erik Darling
Zgadzam się, że mój jest raczej komentarzem niż odpowiedzią. Cóż, zaakceptowana odpowiedź nie jest tak naprawdę odpowiedzią, z wyjątkiem tego, że mówi, że lepiej nie ufać zamówieniu - i o to właśnie chodziło. Plan wykonania pokazuje, że faktycznie wykonuje sortowanie, a jeśli dodamy wyraźne zamówienie, otrzymamy drugi sort. Ale to NIE jest dowód, to tylko część wiedzy empirycznej
Eske Rahn
(Oczywiście robi to tylko wtedy, gdy nie ma odpowiedniego indeksu, którego mógłby użyć, aby uzyskać dostęp do tabeli, ale dodał go tylko, aby pokazać, że jawne wydawanie zamówienia nie jest zazwyczaj bezpłatne)
Eske Rahn