SQL RANK()vs ROW_NUMBER()

时间:2011-10-12 22:26:38

标签: sql sql-server tsql

我对这些之间的差异感到困惑。运行以下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

8 个答案:

答案 0 :(得分:282)

如果您在特定排序值的分区中有联系,则只能看到差异。

在这种情况下,

RANKDENSE_RANK是确定性的,排序和分区列具有相同值的所有行最终会得到相同的结果,而ROW_NUMBER将是任意的(StyleID将是任意的(非确定性地)将增量结果分配给绑定的行。

示例:(所有行都具有相同的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 排序时,前3行是绑定的)

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。 {{1}}也为所有三行分配相同的排名,但是下一个不同的值被赋值为2.

答案 1 :(得分:189)

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

等级:为每行开1的唯一编号,除了具有重复值的行,在这种情况下,分配相同的排名,并且每个重复排名的序列中都会出现间隙

答案 2 :(得分:25)

This article covers an interesting relationship between ROW_NUMBER() and DENSE_RANK()RANK()函数未被特别处理)。当您需要在ROW_NUMBER()语句中生成SELECT DISTINCT时,ROW_NUMBER()会在{{1>}关键字移除之前生成不同的值。例如。这个查询

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()子句中的所有其他列才能正常工作。

原因是逻辑上window functions are calculated before DISTINCT is applied

比较所有三个功能

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

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

答案 3 :(得分:6)

不带分区子句的简单查询:

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 

输出:

    --------|-------|-----------|----------
    sal     |Rank   |DenseRank  |RowNumber
    --------|-------|-----------|----------
    5000    |1      |1          |1
    3000    |2      |2          |2
    3000    |2      |2          |3
    2975    |4      |3          |4
    2850    |5      |4          |5
    --------|-------|-----------|----------

答案 4 :(得分:3)

很多:

行的等级是一行加上相关行之前的等级数。

Row_number是行的不同排名,排名没有任何差距。

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

答案 5 :(得分:0)

看看这个例子。

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

插入一些数据

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')

为1

重复相同的值
  

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

全部查看

SELECT * FROM #TestTable

查看结果

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

需要了解不同的

答案 6 :(得分:0)

我没有对排名做过任何事情,但今天我用row_number()发现了这个。

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

这将导致一些重复的行号,因为在我的情况下,每个名称都包含所有项目。每个项目将按销售数量排序。

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

答案 7 :(得分:-1)

另外,在使用RANK时,请注意PARTITION中的ORDER BY(例如使用标准的AdventureWorks数据库)。

  

SELECT as1.SalesOrderID,as1.SalesOrderDetailID,RANK()OVER   (PARTITION BY as1.SalesOrderID ORDER BY as1.SalesOrderID)ranknoequal   ,RANK()OVER(PARTITION BY as1.SalesOrderID ORDER BY   as1.SalesOrderDetailId)ranknodiff来自Sales.SalesOrderDetail as1   WHERE SalesOrderId = 43659 ORDER BY SalesOrderDetailId;

给出结果:

SalesOrderID SalesOrderDetailID rank_same_as_partition rank_salesorderdetailid
43659 1 1 1
43659 2 1 2
43659 3 1 3
43659 4 1 4
43659 5 1 5
43659 6 1 6
43659 7 1 7
43659 8 1 8
43659 9 1 9
43659 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)rank_orderqty   FROM Sales.SalesOrderDetail as1 WHERE SalesOrderId = 43659 ORDER BY   OrderQty;

给出:

SalesOrderID OrderQty rank_salesorderid rank_orderqty
43659 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 1 9
43659 3 1 9
43659 4 1 11
43659 6 1 12

注意当我们在ORDER BY中使用OrderQty(最右边的第二列表)时,Rank会如何变化,以及当我们在ORDER BY中使用SalesOrderDetailID(最右边的第一列表)时它如何变化。