ROW_NUMBER (Transact-SQL)

Si applica a: SQL Server Database SQL di Azure Istanza gestita di SQL di Azure Azure Synapse Analytics Piattaforma di strumenti analitici (PDW) Endpoint di analisi SQL in Microsoft Fabric Warehouse in Microsoft Fabric

Numera l'output di un set di risultati. In particolare, restituisce il numero sequenziale di una riga all'interno di una partizione di un set di risultati, a partire da 1 per la prima riga di ogni partizione.

ROW_NUMBER e RANK sono simili. ROW_NUMBER numera tutte le righe in sequenza (ad esempio 1, 2, 3, 4, 5). RANK fornisce lo stesso valore numerico per i valori equivalenti (ad esempio 1, 2, 2, 4, 5).

Nota

ROW_NUMBER è un valore temporaneo calcolato al momento dell'esecuzione della query. Per mantenere i numeri in una tabella, vedere Proprietà IDENTITY e SEQUENCE.

Convenzioni relative alla sintassi Transact-SQL

Sintassi

ROW_NUMBER ( )   
    OVER ( [ PARTITION BY value_expression , ... [ n ] ] order_by_clause )  

Argomenti

PARTITION BY value_expression
Suddivide il set di risultati generato dalla clausola FROM in partizioni alle quali viene applicata la funzione ROW_NUMBER. value_expression specifica la colonna in base alla quale viene partizionato il set di risultati. Se PARTITION BY non viene specificato, la funzione considera tutte le righe del set di risultati della query come un unico gruppo. Per altre informazioni, vedere Clausola OVER (Transact-SQL).

order_by_clause
La clausola ORDER BY determina la sequenza in base alla quale alle righe viene assegnato un valore univoco ROW_NUMBER all'interno di una partizione specificata. Questo argomento è obbligatorio. Per altre informazioni, vedere Clausola OVER (Transact-SQL).

Tipi restituiti

bigint

Osservazioni generali

Non esiste alcuna garanzia che le righe restituite da una query che usa ROW_NUMBER() vengano ordinate esattamente allo stesso modo a ogni esecuzione, a meno che le condizioni seguenti non siano vere.

  • Univocità dei valori della colonna partizionata.

  • Univocità dei valori delle colonne ORDER BY.

  • Univocità delle combinazioni di valori della colonna di partizione e delle colonne ORDER BY.

Se le ORDER BY colonne non sono univoche all'interno dei risultati, è consigliabile usare RANK() o DENSE_RANK().

ROW_NUMBER() è non deterministico. Per altre informazioni, vedere Funzioni deterministiche e non deterministiche.

Esempi

R. Esempi semplici

La query seguente restituisce le quattro tabelle di sistema in ordine alfabetico.

SELECT 
  name, recovery_model_desc
FROM sys.databases 
WHERE database_id < 5
ORDER BY name ASC;

Il set di risultati è il seguente.

name recovery_model_desc
master SEMPLICE
model FULL
msdb SEMPLICE
tempdb SEMPLICE

Per aggiungere una colonna con i numeri di riga davanti a ogni riga, aggiungere una colonna con la funzione ROW_NUMBER, in questo caso denominata Row#. È necessario spostare in alto la clausola ORDER BY, accanto alla clausola OVER.

SELECT 
  ROW_NUMBER() OVER(ORDER BY name ASC) AS Row#,
  name, recovery_model_desc
FROM sys.databases 
WHERE database_id < 5;

Il set di risultati è il seguente.

N. di riga name recovery_model_desc
1 master SEMPLICE
2 model FULL
3 msdb SEMPLICE
4 tempdb SEMPLICE

La PARTITION BY clausola nella recovery_model_desc colonna riavvia la numerazione quando il recovery_model_desc valore cambia.

SELECT 
  ROW_NUMBER() OVER(PARTITION BY recovery_model_desc ORDER BY name ASC) 
    AS Row#,
  name, recovery_model_desc
FROM sys.databases WHERE database_id < 5;

Il set di risultati è il seguente.

N. di riga name recovery_model_desc
1 model FULL
1 master SEMPLICE
2 msdb SEMPLICE
3 tempdb SEMPLICE

B. Restituzione del numero di riga per i venditori

Nell'esempio seguente viene calcolato un numero di riga per i venditori in Adventure Works Cycles in base alla classificazione delle vendite dall'inizio dell'anno alla data corrente.

USE AdventureWorks2022;   
GO  
SELECT ROW_NUMBER() OVER(ORDER BY SalesYTD DESC) AS Row,   
    FirstName, LastName, ROUND(SalesYTD,2,1) AS "Sales YTD"   
FROM Sales.vSalesPerson  
WHERE TerritoryName IS NOT NULL AND SalesYTD <> 0;  

Il set di risultati è il seguente.

  
Row FirstName    LastName               SalesYTD  
--- -----------  ---------------------- -----------------  
1   Linda        Mitchell               4251368.54  
2   Jae          Pak                    4116871.22  
3   Michael      Blythe                 3763178.17  
4   Jillian      Carson                 3189418.36  
5   Ranjit       Varkey Chudukatil      3121616.32  
6   José         Saraiva                2604540.71  
7   Shu          Ito                    2458535.61  
8   Tsvi         Reiter                 2315185.61  
9   Rachel       Valdez                 1827066.71  
10  Tete         Mensa-Annan            1576562.19  
11  David        Campbell               1573012.93  
12  Garrett      Vargas                 1453719.46  
13  Lynn         Tsoflias               1421810.92  
14  Pamela       Ansman-Wolfe           1352577.13  

C. Restituzione di un subset di righe

Nell'esempio seguente vengono calcolati solo i numeri di riga per tutte le righe nella tabella SalesOrderHeader nell'ordine di OrderDate e vengono restituite le righe da 50 a 60 incluse.

USE AdventureWorks2022;  
GO  
WITH OrderedOrders AS  
(  
    SELECT SalesOrderID, OrderDate,  
    ROW_NUMBER() OVER (ORDER BY OrderDate) AS RowNumber  
    FROM Sales.SalesOrderHeader   
)   
SELECT SalesOrderID, OrderDate, RowNumber    
FROM OrderedOrders   
WHERE RowNumber BETWEEN 50 AND 60;  

D. Utilizzo di ROW_NUMBER() con PARTITION

Nell'esempio seguente viene utilizzato l'argomento PARTITION BY per suddividere il set di risultati della query in base alla colonna TerritoryName. La clausola ORDER BY specificata nella clausola OVER ordina le righe in ogni partizione in base alla colonna SalesYTD. La clausola ORDER BY nell'istruzione SELECT ordina l'intero set di risultati della query in base al valore di TerritoryName.

USE AdventureWorks2022;  
GO  
SELECT FirstName, LastName, TerritoryName, ROUND(SalesYTD,2,1) AS SalesYTD,  
ROW_NUMBER() OVER(PARTITION BY TerritoryName ORDER BY SalesYTD DESC) 
  AS Row  
FROM Sales.vSalesPerson  
WHERE TerritoryName IS NOT NULL AND SalesYTD <> 0  
ORDER BY TerritoryName;  

Il set di risultati è il seguente.

  
FirstName  LastName             TerritoryName        SalesYTD      Row  
---------  -------------------- ------------------   ------------  ---  
Lynn       Tsoflias             Australia            1421810.92    1  
José       Saraiva              Canada               2604540.71    1  
Garrett    Vargas               Canada               1453719.46    2  
Jillian    Carson               Central              3189418.36    1  
Ranjit     Varkey Chudukatil    France               3121616.32    1  
Rachel     Valdez               Germany              1827066.71    1  
Michael    Blythe               Northeast            3763178.17    1  
Tete       Mensa-Annan          Northwest            1576562.19    1  
David      Campbell             Northwest            1573012.93    2  
Pamela     Ansman-Wolfe         Northwest            1352577.13    3  
Tsvi       Reiter               Southeast            2315185.61    1  
Linda      Mitchell             Southwest            4251368.54    1  
Shu        Ito                  Southwest            2458535.61    2  
Jae        Pak                  United Kingdom       4116871.22    1  

Esempi: Azure Synapse Analytics e Piattaforma di strumenti analitici (PDW)

E. Restituzione del numero di riga per i venditori

L'esempio seguente restituisce il valore ROW_NUMBER per i venditori in base alle rispettive quote di vendita assegnate.

-- Uses AdventureWorks  
  
SELECT ROW_NUMBER() OVER(ORDER BY SUM(SalesAmountQuota) DESC) 
    AS RowNumber,  
    FirstName, LastName,   
    CONVERT(varchar(13), SUM(SalesAmountQuota),1) AS SalesQuota   
FROM dbo.DimEmployee AS e  
INNER JOIN dbo.FactSalesQuota AS sq  
    ON e.EmployeeKey = sq.EmployeeKey  
WHERE e.SalesPersonFlag = 1  
GROUP BY LastName, FirstName;  

Set di risultati parziale:


RowNumber  FirstName  LastName            SalesQuota  
---------  ---------  ------------------  -------------  
1          Jillian    Carson              12,198,000.00  
2          Linda      Mitchell            11,786,000.00  
3          Michael    Blythe              11,162,000.00  
4          Jae        Pak                 10,514,000.00  

F. Utilizzo di ROW_NUMBER() con PARTITION

Nell'esempio seguente viene illustrato l'utilizzo della funzione ROW_NUMBER con l'argomento PARTITION BY. Ciò determina la numerazione, da parte della funzione ROW_NUMBER, delle righe in ogni partizione.

-- Uses AdventureWorks  
  
SELECT ROW_NUMBER() OVER(PARTITION BY SalesTerritoryKey 
        ORDER BY SUM(SalesAmountQuota) DESC) AS RowNumber,  
    LastName, SalesTerritoryKey AS Territory,  
    CONVERT(varchar(13), SUM(SalesAmountQuota),1) AS SalesQuota   
FROM dbo.DimEmployee AS e  
INNER JOIN dbo.FactSalesQuota AS sq  
    ON e.EmployeeKey = sq.EmployeeKey  
WHERE e.SalesPersonFlag = 1  
GROUP BY LastName, FirstName, SalesTerritoryKey;  

Set di risultati parziale:

 
RowNumber  LastName            Territory  SalesQuota  
---------  ------------------  ---------  -------------  
1          Campbell            1           4,025,000.00  
2          Ansman-Wolfe        1           3,551,000.00  
3          Mensa-Annan         1           2,275,000.00  
1          Blythe              2          11,162,000.00  
1          Carson              3          12,198,000.00  
1          Mitchell            4          11,786,000.00  
2          Ito                 4           7,804,000.00  

Vedi anche

RANK (Transact-SQL)
DENSE_RANK (Transact-SQL)
NTILE (Transact-SQL)