何时选择rank()而不是dense_rank()或row_number()

Ank*_*kur 11 sql sql-server hive hiveql

由于我们可以使用 获取分配的行号,row_number()并且如果我们想使用 查找每行的排名而不跳过分区内的任何数字dense_rank(),为什么我们需要rank()函数,我想不出该rank()函数提供的任何用例要么不能实现这一点dense_rank()row_number()

有没有rank()最适合的用例?

Tim*_*sen 11

当将RANK或应用于DENSE_RANK没有关系的列时,它们都会产生由 生成的相同序列ROW_NUMBERRANK和之间的区别DENSE_RANK出现在关系的存在中,并且是微妙的。考虑下表以及行号、排名和密集排名值:

SALARY | ROW_NUMBER | RANK | DENSE_RANK
1000   | 1          | 1    | 1
1500   | 2          | 2    | 2
1500   | 3          | 2    | 2
2000   | 4          | 4    | 3
2200   | 5          | 5    | 4
2500   | 6          | 6    | 5
2500   | 7          | 6    | 5
2500   | 8          | 6    | 5
3000   | 9          | 9    | 6
Run Code Online (Sandbox Code Playgroud)

希望您可以在上面看到,当出现两个或多个记录的平局时,两者RANK都会DENSE_RANK为具有相同值的所有记录分配相同的排名。然而,它们的不同之处在于,RANK继续与系列一致的排名计数ROW_NUMBER,而DENSE_RANK不是,而是使用重复排名后的下一个值继续排名计数。

现在回答你的问题,是选择RANK还是DENSE_RANK取决于你的要求。例如,如果您要报告获胜者,并且始终需要报告第一名、第二名和第三名,无论每个名次的平局如何,您都可以使用DENSE_RANK。否则,您将使用RANK,这可能意味着没有第二名或第三名。如果您确定永远不会有重复项,那么您可以使用ROW_NUMBER.


Som*_*omy 8

下面的例子应该有助于说明差异。(以下示例的数据库小提琴链接 - https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=cef0a4da7559de657aae332491a9c500

\n
CREATE TABLE t AS\nSELECT \'p\' v FROM dual UNION ALL\nSELECT \'p\'   FROM dual UNION ALL\nSELECT \'p\'   FROM dual UNION ALL\nSELECT \'q\'   FROM dual UNION ALL\nSELECT \'r\'   FROM dual UNION ALL\nSELECT \'r\'   FROM dual UNION ALL\nSELECT \'s\'   FROM dual UNION ALL\nSELECT \'t\'   FROM dual;\n\nSELECT\n  v,\n  ROW_NUMBER() OVER (ORDER BY v) row_number,\n  RANK()       OVER (ORDER BY v) rank,\n  DENSE_RANK() OVER (ORDER BY v) dense_rank\nFROM t\nORDER BY v;\nThe above will yield:\n\n+---+------------+------+------------+\n| V | ROW_NUMBER | RANK | DENSE_RANK |\n+---+------------+------+------------+\n| p |          1 |    1 |          1 |\n| p |          2 |    1 |          1 |\n| p |          3 |    1 |          1 |\n| q |          4 |    4 |          2 |\n| r |          5 |    5 |          3 |\n| r |          6 |    5 |          3 |\n| s |          7 |    7 |          4 |\n| t |          8 |    8 |          5 |\n+---+------------+------+------------+\n\n
Run Code Online (Sandbox Code Playgroud)\n

RANK 和 DENSE_RANK 的平局被分配相同的排名,但是在平局后的 RANK 中,您将获得跳过下一个排名的排名排名。最后以粗体标记的部分是 RANK 和 DENSE_RANK 之间的唯一区别。在 DENSE_RANK 中,数字不会被跳过。

\n

一个很好的类比是,想象一下你们班上有 2 名学生获得了最高的总分。所以,第一名的位置是平的。你必须把一等奖颁给他们俩。现在,总分紧随最高分之后的学生,您将分配给他/她什么位置。如果你问 RANK() 函数 - 它会告诉你第三,因为第一位置被 2 人占据。但是,如果您询问 DENSE_RANK() 函数 - 它会告诉您第二名,因为它不会跳过任何排名,因此在这种情况下,第三名将授予总分紧随第二名的人之后的另一个人。而如果您的问题是您只有一个第一名的奖品,则只有一名获奖者:-),那么 ROW_NUMBER 将为您解决这个问题,因为 ROW_NUMNER() 会将第一和第二名随机分配给获得最高分的学生(类似于彩票),因此在这种情况下,第三个位置仍然不存在矛盾。

\n

现在进入 RANK 的用例:我知道很多资格考试都使用 RANK() 方法(不一定是数据库中的排名函数,而是相同的算法或方法)来筛选自比赛以来的学生人数有时关系可能非常密切,因此关系并不罕见。然而,问题是 - 有一个特定的排名让 \xe2\x80\x99s 说 50 用作截止值,但同时它们有固定数量的座位,不能超过。因此,如果出现平局,您必须向两个学生授予相同的排名,因为如果两个学生得分相同,您就无能为力,但是下一个排名将被跳过,否则座位将被填满。这类似于足球联赛,在联赛阶段结束时,多支球队的积分相同。现在在这种联赛中,你可以使用其他标准,例如进球数等来消除季后赛的平局,但在检查的情况下,你当然不能通过重新检查来消除平局。这是一个非常实用的用例,说明了该概念有时可以在哪些地方有用。

\n