SELECT ROW_NUMBER () è garantito per restituire risultati ordinati in base ai numeri di riga generati?


10

Ad esempio, prendere in considerazione la query SQL:

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

Qui osservo i risultati restituiti ordinati per A. [Nome]. Se cambio la colonna di ordinamento definita nella funzione ROW_NUMBER in un'altra colonna, i risultati vengono nuovamente ordinati per quella colonna.

Mi aspettavo che il numero di riga fosse assegnato alle righe ma non mi aspettavo che le righe tornassero ordinate in base agli stessi criteri. Questo è semplicemente un effetto collaterale di come viene eseguita la query (nel mio caso su SQL Server 2008 R2) o questo comportamento è garantito? (Non ho trovato alcun riferimento a tale garanzia).


10
Non c'è mai alcuna garanzia. Mai. A meno che tu non dica a SQL Server come ordinare qualcosa, è libero di restituire i dati nell'ordine che preferiscono. Escludendo l'ordine per, stai dicendo a SQL Server che non ti interessa l'ordine. Se desideri una garanzia, digita già la clausola ORDER BY.
Aaron Bertrand

C'è una buona ragione per chiederlo in quanto la clausola order-by in questione è molto complessa e quindi la copia crea sia zavorra di manutenzione del codice che aumenta la probabilità di futuri difetti. L'altra alternativa è un refactoring minore che pensavo di poter evitare se lo standard SQL definisse un ordinamento implicito. In ogni caso, ero solo interessato alla presenza di documentazione formale su questo punto.
redcalx,

1
quindi perché non porre questa domanda?
Aaron Bertrand

Risposte:


14

Se avessi posto la domanda, penso che volessi davvero fare:

Come posso ordinare ROW_NUMBER()senza ripetere l' ORDER BYespressione complessa ?

Avremmo potuto dirti di creare un alias per l' ROW_NUMBER()espressione e quindi ordinare utilizzando l'alias:

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

Ora devi solo cambiare l'espressione in un posto e l'ordinamento risultante si baserà su quell'espressione senza doverlo ripetere.


6
In realtà, repeating the complex ORDER BY expressionnon garantisce nemmeno che l'output verrà emesso dall'ordine ROW_NUMBER (). A meno che le colonne nella clausola ORDER BY non costituiscano una chiave univoca.
孔夫子

22

Assolutamente no. Prova:

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

L'unico modo per garantire un ordine in SQL è richiederlo, utilizzare ORDER BYil risultato stesso.


OK, aggiungerò un'ulteriore qualifica: i risultati garantiti saranno ordinati se viene specificata solo una clausola ROW_NUMBER ().
redcalx,

22
L'unico modo per garantire un ordine in SQL è richiederlo
Remus Rusanu,

0

In realtà la (vecchia) domanda potrebbe essere estesa per includere anche la partizione per parte, poiché sembra che ci sia un ordine implicito prima dalla partizione e poi dall'ordine per parte

Quindi non è così semplice come alcuni hanno suggerito di assegnare il numero di riga e usarlo per l'ordinazione.

Avremmo bisogno di un sql nidificato che estrae anche la partizione per clausola (se non vogliamo semplicemente ripeterla ovviamente)

Empiricamente sembriamo ottenere l'ultima linea di ordinamento implicitamente

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

Ma ciò che ci manca è qualsiasi prova o garanzia che sia sempre valida.

(Se ci sono più chiamate Row_Number () in gioco, è l'ULTIMA che sembra dare l'ordinamento)

NOTA ANCHE se si aggiunge esplicitamente l' ordine dal piano di esecuzione mostra chiaramente una fase di ordinamento finale e l'ordinamento di un set già ordinato è il caso peggiore, quindi ci vuole molto più tempo con Order By che senza


1
Questo in realtà non risponde alla domanda e sembra in disaccordo sia con la risposta accettata, sia con una risposta molto votata.
Erik Darling,

Sono d'accordo che il mio è più un commento che una risposta. Beh, la risposta accettata non è in realtà una risposta, tranne per il fatto che è meglio non fidarci dell'ordine - ed era quello che era la domanda. Il piano di esecuzione può vedere che esegue effettivamente un ordinamento e se aggiungiamo un ordine esplicito per, otteniamo un secondo ordinamento. Ma questa NON è una prova, è solo una parte della conoscenza empirica
Eske Rahn,

(Ovviamente fa solo il genere se non esiste un indice adatto che può usare per accedere alla tabella, ma lo ha aggiunto solo per mostrare che non è generalmente gratuito dare esplicitamente l'ordine entro)
Eske Rahn
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.