In SQL Server, il ROW_NUMBER()
La funzione consente di numerare l'output di un set di risultati. Restituisce il numero sequenziale di ogni riga, a partire da 1.
Se specifichi le partizioni per il set di risultati, ciascuna partizione fa ricominciare la numerazione (ovvero la numerazione inizierà da 1 per la prima riga in ciascuna partizione).
Sintassi
La sintassi è questa:
ROW_NUMBER ( ) OVER ( [ PARTITION BY value_expression , ... [ n ] ] order_by_clause )
PARTITION BY value_expression
è facoltativo. Divide il set di risultati prodotto dal FROM
clausola in partizioni a cui viene applicata la funzione. valore_espressione specifica la colonna in base alla quale viene partizionato il set di risultati. Se il PARTITION BY
non è specificata, tutte le righe del set di risultati della query vengono trattate come un unico gruppo.
ROW_NUMBER
univoco all'interno di una partizione specificata.
Nota che il OVER
normalmente accetta una clausola
Esempio 1 – Utilizzo di base
Ecco un esempio di base che mostra come funziona questa funzione:
SELECT ROW_NUMBER() OVER (ORDER BY AlbumId ASC) 'Row', AlbumId, AlbumName FROM Albums;
Risultato:
+-------+-----------+--------------------------+ | Row | AlbumId | AlbumName | |-------+-----------+--------------------------| | 1 | 1 | Powerslave | | 2 | 2 | Powerage | | 3 | 3 | Singing Down the Lane | | 4 | 4 | Ziltoid the Omniscient | | 5 | 5 | Casualties of Cool | | 6 | 6 | Epicloud | | 7 | 7 | Somewhere in Time | | 8 | 8 | Piece of Mind | | 9 | 9 | Killers | | 10 | 10 | No Prayer for the Dying | | 11 | 11 | No Sound Without Silence | | 12 | 12 | Big Swing Face | | 13 | 13 | Blue Night | | 14 | 14 | Eternity | | 15 | 15 | Scandinavia | | 16 | 16 | Long Lost Suitcase | | 17 | 17 | Praise and Blame | | 18 | 18 | Along Came Jones | | 19 | 19 | All Night Wrong | | 20 | 20 | The Sixteen Men of Tain | | 21 | 21 | Yo Wassup | | 22 | 22 | Busted | +-------+-----------+--------------------------+
In questo caso possiamo vedere che i numeri di riga si allineano perfettamente con i valori in AlbumId
colonna. Questo è puramente casuale. Ciò accade perché AlbumId
colonna utilizza un valore incrementale che inizia da 1, che è anche ciò che ROW_NUMBER()
usi.
La numerazione delle righe è correlata a AlbumId
colonna nella misura in cui è ordinata in base a quella colonna. Ma ciò non significa che i valori debbano essere gli stessi.
Esempio 2:aggiungi una clausola WHERE
Aggiunta di un WHERE
la clausola dimostrerà cosa intendo.
SELECT ROW_NUMBER() OVER (ORDER BY AlbumId ASC) 'Row', AlbumId, AlbumName FROM Albums WHERE AlbumId > 15;
Risultato:
+-------+-----------+-------------------------+ | Row | AlbumId | AlbumName | |-------+-----------+-------------------------| | 1 | 16 | Long Lost Suitcase | | 2 | 17 | Praise and Blame | | 3 | 18 | Along Came Jones | | 4 | 19 | All Night Wrong | | 5 | 20 | The Sixteen Men of Tain | | 6 | 21 | Yo Wassup | | 7 | 22 | Busted | +-------+-----------+-------------------------+
Esempio 3:cambiare l'ordine
Anche l'ordine decrescente anziché crescente dimostra questo concetto.
SELECT ROW_NUMBER() OVER (ORDER BY AlbumId DESC) 'Row', AlbumId, AlbumName FROM Albums;
Risultato:
+-------+-----------+--------------------------+ | Row | AlbumId | AlbumName | |-------+-----------+--------------------------| | 1 | 22 | Busted | | 2 | 21 | Yo Wassup | | 3 | 20 | The Sixteen Men of Tain | | 4 | 19 | All Night Wrong | | 5 | 18 | Along Came Jones | | 6 | 17 | Praise and Blame | | 7 | 16 | Long Lost Suitcase | | 8 | 15 | Scandinavia | | 9 | 14 | Eternity | | 10 | 13 | Blue Night | | 11 | 12 | Big Swing Face | | 12 | 11 | No Sound Without Silence | | 13 | 10 | No Prayer for the Dying | | 14 | 9 | Killers | | 15 | 8 | Piece of Mind | | 16 | 7 | Somewhere in Time | | 17 | 6 | Epicloud | | 18 | 5 | Casualties of Cool | | 19 | 4 | Ziltoid the Omniscient | | 20 | 3 | Singing Down the Lane | | 21 | 2 | Powerage | | 22 | 1 | Powerslave | +-------+-----------+--------------------------+
Esempio 4 – Ordine per colonna diversa
E già che ci siamo, ordiniamo per AlbumName
colonna invece.
SELECT ROW_NUMBER() OVER (ORDER BY AlbumName ASC) 'Row', AlbumId, AlbumName FROM Albums;
Risultato:
+-------+-----------+--------------------------+ | Row | AlbumId | AlbumName | |-------+-----------+--------------------------| | 1 | 19 | All Night Wrong | | 2 | 18 | Along Came Jones | | 3 | 12 | Big Swing Face | | 4 | 13 | Blue Night | | 5 | 22 | Busted | | 6 | 5 | Casualties of Cool | | 7 | 6 | Epicloud | | 8 | 14 | Eternity | | 9 | 9 | Killers | | 10 | 16 | Long Lost Suitcase | | 11 | 10 | No Prayer for the Dying | | 12 | 11 | No Sound Without Silence | | 13 | 8 | Piece of Mind | | 14 | 2 | Powerage | | 15 | 1 | Powerslave | | 16 | 17 | Praise and Blame | | 17 | 15 | Scandinavia | | 18 | 3 | Singing Down the Lane | | 19 | 7 | Somewhere in Time | | 20 | 20 | The Sixteen Men of Tain | | 21 | 21 | Yo Wassup | | 22 | 4 | Ziltoid the Omniscient | +-------+-----------+--------------------------+
Esempio 5 – Partizioni
Come accennato, puoi anche dividere i risultati in partizioni. Quando lo fai, la numerazione ricomincia da 1 per ogni nuova partizione.
Esempio:
SELECT Genre, ROW_NUMBER() OVER (PARTITION BY Genre ORDER BY AlbumId ASC) 'Row', AlbumId, AlbumName FROM Albums INNER JOIN Genres ON Albums.GenreId = Genres.GenreId;
Risultato:
+---------+-------+-----------+--------------------------+ | Genre | Row | AlbumId | AlbumName | |---------+-------+-----------+--------------------------| | Country | 1 | 3 | Singing Down the Lane | | Country | 2 | 21 | Yo Wassup | | Country | 3 | 22 | Busted | | Jazz | 1 | 12 | Big Swing Face | | Jazz | 2 | 19 | All Night Wrong | | Jazz | 3 | 20 | The Sixteen Men of Tain | | Pop | 1 | 11 | No Sound Without Silence | | Pop | 2 | 13 | Blue Night | | Pop | 3 | 14 | Eternity | | Pop | 4 | 15 | Scandinavia | | Pop | 5 | 16 | Long Lost Suitcase | | Pop | 6 | 17 | Praise and Blame | | Pop | 7 | 18 | Along Came Jones | | Rock | 1 | 1 | Powerslave | | Rock | 2 | 2 | Powerage | | Rock | 3 | 4 | Ziltoid the Omniscient | | Rock | 4 | 5 | Casualties of Cool | | Rock | 5 | 6 | Epicloud | | Rock | 6 | 7 | Somewhere in Time | | Rock | 7 | 8 | Piece of Mind | | Rock | 8 | 9 | Killers | | Rock | 9 | 10 | No Prayer for the Dying | +---------+-------+-----------+--------------------------+
Ancora una volta possiamo vedere che il ROW_NUMBER
e il AlbumId
le colonne sono completamente non correlate.
In questo caso partizione per Genre
colonna. In questo modo la numerazione ricomincia da 1 per ogni genere.