我搞不懂它们之间的区别。运行下面的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

当前回答

注意,所有这些窗口函数都返回一个类似整型的值。

数据库通常会选择BIGINT数据类型,这占用的空间比我们需要的大得多。而且,我们很少需要从-9,223,372,036,854,775,808到+9,223,372,036,854,775,807的范围。

将结果转换为BYTEINT、SMALLINT或INTEGER。

这些现代系统和硬件是如此强大,所以你可能永远不会看到有意义的额外资源使用,但我认为这是最佳实践。

其他回答

本文将介绍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子句中的所有其他列才能正常工作。

这样做的原因是,从逻辑上讲,窗口函数是在应用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

... 你会得到:

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

注意,所有这些窗口函数都返回一个类似整型的值。

数据库通常会选择BIGINT数据类型,这占用的空间比我们需要的大得多。而且,我们很少需要从-9,223,372,036,854,775,808到+9,223,372,036,854,775,807的范围。

将结果转换为BYTEINT、SMALLINT或INTEGER。

这些现代系统和硬件是如此强大,所以你可能永远不会看到有意义的额外资源使用,但我认为这是最佳实践。

ROW_NUMBER:为以1开头的每一行返回一个唯一的数字。对于具有重复值的行,将任意分配数字。

Rank:为从1开始的每一行分配一个唯一的数字,但有重复值的行除外,在这种情况下,分配相同的排名,并且在每个重复排名的序列中出现一个空白。

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

选择as1。SalesOrderID as1。SalesOrderDetailID, RANK()结束 分区由as1。SalesOrderID ORDER BY as1。) ranknoequal , RANK() OVER(分区为as1.)由SalesOrderID订购 as1。SalesOrderDetailId) ranknodiff FROM Sales。SalesOrderDetail as1 SalesOrderId = 43659;

给出结果:

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:

选择as1。SalesOrderID as1。OrderQty, RANK() OVER (PARTITION BY as1。SalesOrderID ORDER BY as1。ranknoequal, RANK() OVER(分区为as1。SalesOrderID ORDER BY as1。OrderQty) 从销售。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(最右边的列第一表)时,Rank是如何变化的。

相当多:

一行的秩是1加上前面一行的秩数。

Row_number是行的唯一秩,在秩上没有任何差距。

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