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开始的每一行分配一个唯一的编号,但具有重复值的行除外,在这种情况下,将分配相同的排名,并且在每个重复排名的序列中出现空位。

如果您在某个分区中具有特定sorting值的关系,则只会看到不同之处。

在这种情况下, RANKDENSE_RANK是确定性的,对于sorting列和分区列,具有相同值的所有行将以相同结果结束,而ROW_NUMBER将任意(非确定性地)将增加结果分配给绑定行。

例如:(所有行都具有相同的StyleID因此在同一个分区中,并且在该分区内,前3行在按IDsorting时是连接的)

 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值保持不变,然后跳到4DENSE_RANK也为所有三行分配相同的等级,但是下一个不同的值被赋值为2。

本文介绍ROW_NUMBER()DENSE_RANK()RANK()函数没有特别处理) 之间有趣的关系 。 当您需要在SELECT DISTINCT语句中生成ROW_NUMBER()时, 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 | +---+------------+ 

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

所有三个function相比较

使用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 

…你会得到:

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

相当有点:

一行的等级是一个加上所述行之前的行列的数量。

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

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

看这个例子。

 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 

需要了解不同

另外,在使用RANK时要注意PARTITION中的ORDER BY(例如使用标准的AdventureWorks db)。

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 FROM Sales.SalesOrderDetail as1 WHERE SalesOrderId = 43659 ORDER BY SalesOrderDetailId;

给出结果:

SalesOrderID SalesOrderDetailID rank_sales_deviceID 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

但是如果改成order(使用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(最右边的列第一个表)时它是如何改变的。

我没有做任何与排名,但我今天用row_number()发现了这一点。

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

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

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