SQL RANK()与ROW_NUMBER()

dot*_*est 172 sql t-sql sql-server

我对这些之间的差异感到困惑.运行以下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
Run Code Online (Sandbox Code Playgroud)

Mar*_*ith 302

如果您在特定订购值的分区中存在关联,则只会看到差异.

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  
Run Code Online (Sandbox Code Playgroud)

返回

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
Run Code Online (Sandbox Code Playgroud)

您可以看到,对于三个相同的行,ROW_NUMBER增量,RANK值保持相同然后跳到4.DENSE_RANK也为所有三行分配相同的排名,但是下一个不同的值被赋值为2.

  • 太棒了!...感谢提及DENSE_RANK (24认同)
  • 谢谢你的一个很好的例子.当ROW_NUMBER()更合适时,帮助我意识到我错误地使用了RANK()函数. (6认同)
  • 说真的,这太棒了. (2认同)

Rit*_*esh 202

ROW_NUMBER:返回以1开头的每一行的唯一编号.对于具有重复值的行,将对该数字进行仲裁.

排名:为以1开头的每一行指定唯一编号,但具有重复值的行除外,在这种情况下,将为每个重复排名分配相同的排名并在序列中显示间隙.


Luk*_*der 32

本文介绍了ROW_NUMBER()和之间有趣的关系DENSE_RANK()(RANK()函数没有特别处理).当您需要ROW_NUMBER()SELECT DISTINCT语句上生成时,ROW_NUMBER()将在关键字删除它们之前生成不同的值DISTINCT.例如这个查询

SELECT DISTINCT
  v, 
  ROW_NUMBER() OVER (ORDER BY v) row_number
FROM t
ORDER BY v, row_number
Run Code Online (Sandbox Code Playgroud)

...可能会产生这个结果(DISTINCT没有效果):

+---+------------+
| V | ROW_NUMBER |
+---+------------+
| a |          1 |
| a |          2 |
| a |          3 |
| b |          4 |
| c |          5 |
| c |          6 |
| d |          7 |
| e |          8 |
+---+------------+
Run Code Online (Sandbox Code Playgroud)

鉴于此查询:

SELECT DISTINCT
  v, 
  DENSE_RANK() OVER (ORDER BY v) row_number
FROM t
ORDER BY v, row_number
Run Code Online (Sandbox Code Playgroud)

...在这种情况下产生你可能想要的东西:

+---+------------+
| V | ROW_NUMBER |
+---+------------+
| a |          1 |
| b |          2 |
| c |          3 |
| d |          4 |
| e |          5 |
+---+------------+
Run Code Online (Sandbox Code Playgroud)

请注意,函数的ORDER BY子句DENSE_RANK()将需要子句中的所有其他列SELECT DISTINCT才能正常工作.

这样做的原因是逻辑上,窗口函数在DISTINCT应用之前计算.

所有三个功能相比较

使用PostgreSQL/Sybase/SQL标准语法(WINDOW子句):

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
Run Code Online (Sandbox Code Playgroud)

... 你会得到:

+---+------------+------+------------+
| 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 |
+---+------------+------+------------+
Run Code Online (Sandbox Code Playgroud)

  • ROW_NUMBER 和 DENSE_RANK 在应用不同值之前都会生成值。实际上,所有排名函数或任何函数在应用 DISTINCT 之前都会产生结果。 (2认同)

DSR*_*DSR 12

没有分区子句的简单查询:

select 
    sal, 
    RANK() over(order by sal desc) as Rank,
    DENSE_RANK() over(order by sal desc) as DenseRank,
    ROW_NUMBER() over(order by sal desc) as RowNumber
from employee 
Run Code Online (Sandbox Code Playgroud)

输出:

    --------|-------|-----------|----------
    sal     |Rank   |DenseRank  |RowNumber
    --------|-------|-----------|----------
    5000    |1      |1          |1
    3000    |2      |2          |2
    3000    |2      |2          |3
    2975    |4      |3          |4
    2850    |5      |4          |5
    --------|-------|-----------|----------
Run Code Online (Sandbox Code Playgroud)