我搞不懂它们之间的区别。运行下面的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
只有在分区中为特定排序值设置了关联时,才会看到差异。
在这种情况下,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。
另外,在使用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是如何变化的。
我没有做任何关于秩的事情,但是我今天用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 |
+--------+------+-----+----+
注意,所有这些窗口函数都返回一个类似整型的值。
数据库通常会选择BIGINT数据类型,这占用的空间比我们需要的大得多。而且,我们很少需要从-9,223,372,036,854,775,808到+9,223,372,036,854,775,807的范围。
将结果转换为BYTEINT、SMALLINT或INTEGER。
这些现代系统和硬件是如此强大,所以你可能永远不会看到有意义的额外资源使用,但我认为这是最佳实践。