development

SQL RANK () 대 ROW_NUMBER ()

big-blog 2020. 5. 26. 19:10
반응형

SQL RANK () 대 ROW_NUMBER ()


나는 이들의 차이점에 대해 혼란스러워합니다. 다음 SQL을 실행하면 두 개의 동일한 결과 세트가 나타납니다. 누군가 차이점을 설명해 주시겠습니까?

SELECT ID, [Description], RANK()       OVER(PARTITION BY StyleID ORDER BY ID) as 'Rank'      FROM SubStyle
SELECT ID, [Description], ROW_NUMBER() OVER(PARTITION BY StyleID ORDER BY ID) as 'RowNumber' FROM SubStyle

ROW_NUMBER : 1로 시작하는 각 행의 고유 번호를 반환합니다 . 값이 중복되는 행의 경우 임의로 숫자가 할당됩니다.

순위 : 중복 값이있는 행을 제외하고 1로 시작하는 각 행에 고유 번호를 할당합니다.이 경우 동일한 순위가 할당되고 각 중복 순위의 시퀀스에 간격이 나타납니다.


파티션 내에서 특정 순서 값과의 관계가있는 경우에만 차이점을 볼 수 있습니다.

RANK그리고 DENSE_RANK반면 순서 및 파티션 열 모두에 대해 동일한 값을 가진 모든 행은 동일한 결과로 끝날 것,이 경우에 결정적 ROW_NUMBER임의로 (비는 결정 성)이 묶여 행 증가하는 결과를 부여한다.

예 : (모든 행이 동일 StyleID하므로 동일한 파티션에 있고 해당 파티션 내에서 순서대로 첫 3 개의 행이 연결됨 ID)

WITH T(StyleID, ID)
     AS (SELECT 1,1 UNION ALL
         SELECT 1,1 UNION ALL
         SELECT 1,1 UNION ALL
         SELECT 1,2)
SELECT *,
       RANK() OVER(PARTITION BY StyleID ORDER BY ID)       AS 'RANK',
       ROW_NUMBER() OVER(PARTITION BY StyleID ORDER BY ID) AS 'ROW_NUMBER',
       DENSE_RANK() OVER(PARTITION BY StyleID ORDER BY ID) AS 'DENSE_RANK'
FROM   T  

보고

StyleID     ID       RANK      ROW_NUMBER      DENSE_RANK
----------- -------- --------- --------------- ----------
1           1        1         1               1
1           1        1         2               1
1           1        1         3               1
1           2        4         4               2

세 개의 동일한 행에 대해 ROW_NUMBER증분 증가하면 RANK값이 동일하게 유지되어 도약하는 것을 알 수 4있습니다. DENSE_RANK또한 세 행 모두에 동일한 순위를 할당하지만 다음 고유 값에 값 2가 할당됩니다.


이 문서 간의 흥미로운 관계 커버 ROW_NUMBER()DENSE_RANK() 합니다 ( RANK()함수 특별히 처리하지 않음). 당신이 생성 필요로 할 때 ROW_NUMBER()A의 SELECT DISTINCT문의는 ROW_NUMBER()고유 한 값을 생성합니다 전에 그들이에 의해 제거되는 DISTINCT키워드. 예를 들어이 쿼리

SELECT DISTINCT
  v, 
  ROW_NUMBER() OVER (ORDER BY v) row_number
FROM t
ORDER BY v, row_number

...이 결과를 생성 할 수 있습니다 ( DISTINCT효과가 없음).

+---+------------+
| V | ROW_NUMBER |
+---+------------+
| a |          1 |
| a |          2 |
| a |          3 |
| b |          4 |
| c |          5 |
| c |          6 |
| d |          7 |
| e |          8 |
+---+------------+

이 쿼리는 다음과 같습니다.

SELECT DISTINCT
  v, 
  DENSE_RANK() OVER (ORDER BY v) row_number
FROM t
ORDER BY v, row_number

...이 경우에 원하는 것을 생성합니다.

+---+------------+
| V | ROW_NUMBER |
+---+------------+
| a |          1 |
| b |          2 |
| c |          3 |
| d |          4 |
| e |          5 |
+---+------------+

점을 유의 ORDER BY의 절 DENSE_RANK()기능은 다른 모든 열을해야합니다 SELECT DISTINCT제대로 작동하려면 절.

그 이유는 창 함수가DISTINCT 논리적으로 적용 되기 전에 계산되기 때문 입니다 .

세 기능 모두 비교

Using PostgreSQL / Sybase / SQL standard syntax (WINDOW clause):

SELECT
  v,
  ROW_NUMBER() OVER (window) row_number,
  RANK()       OVER (window) rank,
  DENSE_RANK() OVER (window) dense_rank
FROM t
WINDOW window AS (ORDER BY v)
ORDER BY v

... you'll get:

+---+------------+------+------------+
| V | ROW_NUMBER | RANK | DENSE_RANK |
+---+------------+------+------------+
| a |          1 |    1 |          1 |
| a |          2 |    1 |          1 |
| a |          3 |    1 |          1 |
| b |          4 |    4 |          2 |
| c |          5 |    5 |          3 |
| c |          6 |    5 |          3 |
| d |          7 |    7 |          4 |
| e |          8 |    8 |          5 |
+---+------------+------+------------+

Quite a bit:

The rank of a row is one plus the number of ranks that come before the row in question.

Row_number is the distinct rank of rows, without any gap in the ranking.

http://www.bidn.com/blogs/marcoadf/bidn-blog/379/ranking-functions-row_number-vs-rank-vs-dense_rank-vs-ntile


Look this example.

CREATE TABLE [dbo].#TestTable(
    [id] [int] NOT NULL,
    [create_date] [date] NOT NULL,
    [info1] [varchar](50) NOT NULL,
    [info2] [varchar](50) NOT NULL,
)

Insert some data

INSERT INTO dbo.#TestTable (id, create_date, info1, info2)
VALUES (1, '1/1/09', 'Blue', 'Green')
INSERT INTO dbo.#TestTable (id, create_date, info1, info2)
VALUES (1, '1/2/09', 'Red', 'Yellow')
INSERT INTO dbo.#TestTable (id, create_date, info1, info2)
VALUES (1, '1/3/09', 'Orange', 'Purple')
INSERT INTO dbo.#TestTable (id, create_date, info1, info2)
VALUES (2, '1/1/09', 'Yellow', 'Blue')
INSERT INTO dbo.#TestTable (id, create_date, info1, info2)
VALUES (2, '1/5/09', 'Blue', 'Orange')
INSERT INTO dbo.#TestTable (id, create_date, info1, info2)
VALUES (3, '1/2/09', 'Green', 'Purple')
INSERT INTO dbo.#TestTable (id, create_date, info1, info2)
VALUES (3, '1/8/09', 'Red', 'Blue')

Repeat same Values for 1

INSERT INTO dbo.#TestTable (id, create_date, info1, info2) VALUES (1, '1/1/09', 'Blue', 'Green')

Look All

SELECT * FROM #TestTable

Look your results

SELECT Id,
    create_date,
    info1,
    info2,
    ROW_NUMBER() OVER (PARTITION BY Id ORDER BY create_date DESC) AS RowId,
    RANK() OVER(PARTITION BY Id ORDER BY create_date DESC)    AS [RANK]
FROM #TestTable

Need to understand the different


I haven't done anything with rank, but I discovered this today with row_number().

select item, name, sold, row_number() over(partition by item order by sold) as row from table_name

This will result in some repeating row numbers since in my case each name holds all items. Each item will be ordered by how many were sold.

+--------+------+-----+----+
|glasses |store1|  30 | 1  |
|glasses |store2|  35 | 2  |
|glasses |store3|  40 | 3  |
|shoes   |store2|  10 | 1  |
|shoes   |store1|  20 | 2  |
|shoes   |store3|  22 | 3  |
+--------+------+-----+----+

또한 RANK를 사용할 때 PARTITION (예 : Standard AdventureWorks db가 사용됨)의 ORDER BY에주의하십시오.

선택 as1.SalesOrderID, as1.SalesOrderDetailID, RANK () OVER (PARTITION BY as1.SalesOrderID ORDER BY as1.SalesOrderID) ranknoequal, RANK () OVER (PARTITION BY as1.SalesOrderID ORDER BY as1.SalesOrderDetailedDetaildDetailedDetailedDetailedDetailedDetailedDetaildDetailedDetaildDetaildDetailedDetaildDetailedDetailedDetailedDetailedDetailedDetailedDetailedDetailedDetailedDetailedDetailedDetaildder.com SalesOrderId = 43659 ORDER BY SalesOrderDetailId;

결과를 제공합니다 :

SalesOrderID SalesOrderDetailID rank_same_as_partition rank_salesorderdetailid
43659 1 1
43659 2 1
43 43 3 1 3
43659 4 1 4
43659 5 1 5
43659 6 1 6
43659 7 1
43 43 8 8
8659659 9
4343 10 1 10
43659 11 1 11
43659 12 1 12

그러나 주문을로 변경하면 (OrderQty 사용 :

SELECT as1.SalesOrderID, as1.OrderQty, RANK () OVER (PARTITION BY as1.SalesOrderID ORDER BY as1.SalesOrderID) ranknoequal, RANK () OVER (PARTITION BY as1.SalesOrderID ORDER BY as1.OrderQty FROMEHERS.OrderQty FROMEHERE.FORDERODERQty ROM) SalesOrderId = 43659 주문자 주문 수량;

제공합니다 :

SalesOrderID에 OrderQty rank_salesorderid rank_orderqty
43,659 1 1 1
43659 1 1 1
43659 1 1 1
43659 1 1 1
43659 1 1 1
43659 1 1 1
43659 2 1 7
43659 2 1 7
43659 3 1394
43659 3 1394
43659 4 11 1
43,659 6 1 12

Notice how the Rank changes when we use OrderQty (rightmost column second table) in ORDER BY and how it changes when we use SalesOrderDetailID (rightmost column first table) in ORDER BY.

참고URL : https://stackoverflow.com/questions/7747327/sql-rank-versus-row-number

반응형