分享方式:


ROW_NUMBER (Transact-SQL)

適用於:SQL Server Azure SQL 資料庫 Azure SQL 受控執行個體 Azure Synapse Analytics Analytics Platform System (PDW) Microsoft Fabric 的 SQL 端點分析 Microsoft Fabric 的倉儲

為結果集的輸出編號。 具體來說,傳回結果集分割區內某資料列的序號,序號從 1 開始,每個分割區第一個資料列的序號是 1。

ROW_NUMBERRANK 類似。 ROW_NUMBER 會依序為所有資料列編號 (例如 1、2、3、4、5)。 RANK 為繫結提供相同的數值 (例如 1、2、2、4、5)。

注意

ROW_NUMBER 是查詢在執行時所計算的暫存值。 若要將數字保存在資料表中,請參閱 IDENTITY 屬性SEQUENCE

Transact-SQL 語法慣例

語法

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

引數

PARTITION BY value_expression
FROM 子句所產生的結果集分成套用 ROW_NUMBER 函數的分割區。 value_expression 會指定用於分割結果集的資料行。 如未指定 PARTITION BY,此函數會將查詢結果集的所有資料列視為單一群組。 如需詳細資訊,請參閱 OVER 子句 (Transact-SQL)

order_by_clause
ORDER BY 子句決定了在指定分割區內,將唯一 ROW_NUMBER 指派給資料列的順序。 此為必要。 如需詳細資訊,請參閱 OVER 子句 (Transact-SQL)

傳回型別

bigint

一般備註

除非下列條件成立,否則不保證使用 ROW_NUMBER() 之查詢所傳回的資料列一定會在每次執行時依照相同的方式排列。

  • 分割區資料行的值是唯一的。

  • ORDER BY 資料行的值是唯一的。

  • 分割區資料行和 ORDER BY 資料行的值組合是唯一的。

如果結果 ORDER BY 中的數據行不是唯一的,請考慮使用 RANK()DENSE_RANK()

ROW_NUMBER() 不具決定性。 如需詳細資訊,請參閱 決定性與非決定性函數

範例

A. 簡單範例

下列查詢會依字母順序傳回 4 個系統資料表。

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

結果集如下所示。

NAME recovery_model_desc
master 簡單
model FULL
msdb 簡單
tempdb 簡單

若要在每個資料列前面新增資料列號碼資料行,請新增有 ROW_NUMBER 函數的資料行,在此情況下名為 Row#。 您必須將 ORDER BY 子句移到 OVER 子句。

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

結果集如下所示。

Row# NAME recovery_model_desc
1 master 簡單
2 model FULL
3 msdb 簡單
4 tempdb 簡單

數據 PARTITION BY 行上的 recovery_model_desc 子句會在值變更時 recovery_model_desc 重新啟動編號。

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;

結果集如下所示。

Row# NAME recovery_model_desc
1 model FULL
1 master 簡單
2 msdb 簡單
3 tempdb 簡單

B. 傳回銷售人員的資料列編號

下列範例會根據年初至今的銷售業績排名來計算 Adventure Works Cycles 中銷售人員的資料列編號。

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;  

結果集如下所示。

  
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. 傳回資料列的子集

下列範例會計算 SalesOrderHeader 資料表中所有資料列的編號,並以 OrderDate 順序排列,然後只傳回包含 5060 的資料列。

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. 並用 PARTITION 與 ROW_NUMBER()

下列範例使用 PARTITION BY 引數依據資料行 TerritoryName 分割查詢結果集。 ORDER BY 子句中指定的 OVER 子句會依資料行 SalesYTD 排列每個分割區的資料列。 ORDER BY 陳述式中的 SELECT 子句會依照 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;  

結果集如下所示。

  
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  

範例:Azure Synapse Analytics 和 Analytics Platform System (PDW)

E. 傳回銷售人員的資料列編號

下列範例會根據銷售代表被指派的銷售配額,傳回銷售代表的 ROW_NUMBER

-- 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;  

以下為部分結果集。


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. 並用 PARTITION 與 ROW_NUMBER()

下列範例顯示如何搭配 ROW_NUMBER 引數使用 PARTITION BY 函數。 這會導致 ROW_NUMBER 函數為每個分割區中的資料列編號。

-- 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;  

以下為部分結果集。

 
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  

另請參閱

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