다음을 통해 공유


ROW_NUMBER(Transact-SQL)

적용 대상: SQL Server Azure SQL Database Azure SQL Managed Instance Azure Synapse Analytics Analytics Platform System(PDW) Microsoft Fabric의 SQL 분석 엔드포인트 Microsoft Fabric의 웨어하우스

결과 집합의 출력 번호를 지정합니다. 보다 구체적으로는, 결과 집합 파티션 내의 행 일련 번호를 반환합니다. 각 파티션의 첫 번째 행은 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()는 비결정적입니다. 자세한 내용은 Deterministic and Nondeterministic Functions을 참조하세요.

예제

A. 간단한 예제

다음 쿼리는 알파벳 순서로 4개의 시스템 테이블을 반환합니다.

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

결과 집합은 다음과 같습니다.

name recovery_model_desc
master SIMPLE
model FULL
msdb SIMPLE
tempdb SIMPLE

각 행 앞에 행 번호 열을 추가하려면 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 SIMPLE
2 model FULL
3 msdb SIMPLE
4 tempdb SIMPLE

열의 recovery_model_desc 절은 PARTITION BY 값이 변경되면 번호 매기기를 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 SIMPLE
2 msdb SIMPLE
3 tempdb SIMPLE

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를 기준으로 모든 행의 행 번호를 계산한 후 50에서 60까지의 행만 반환합니다.

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 및 분석 플랫폼 시스템(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)