oracle中的RANK()和DENSE_RANK()函数有什么区别?


150

RANK()DENSE_RANK()函数有什么区别?下emptbl表如何找到第n个薪水?

DEPTNO  EMPNAME    SAL
------------------------------
10       rrr    10000.00
11       nnn    20000.00
11       mmm    5000.00
12       kkk    30000.00
10       fff    40000.00
10       ddd    40000.00
10       bbb    50000.00
10       ccc    50000.00

如果表中的数据具有nulls,如果我想找出nth薪水会怎样?

Answers:


242

RANK为您提供排序分区中的排名。领带被分配相同的等级,而下一等级被跳过。因此,如果您在第2级有3个项目,则列出的下一个级别将是第5级。

DENSE_RANK再次为您提供了已排序分区中的排名,但是这些排名是连续的。如果存在包含多个项目的等级,则不会跳过任何等级。

至于空值,则取决于ORDER BY子句。这是一个简单的测试脚本,您可以使用它来查看会发生什么:

with q as (
select 10 deptno, 'rrr' empname, 10000.00 sal from dual union all
select 11, 'nnn', 20000.00 from dual union all
select 11, 'mmm', 5000.00 from dual union all
select 12, 'kkk', 30000 from dual union all
select 10, 'fff', 40000 from dual union all
select 10, 'ddd', 40000 from dual union all
select 10, 'bbb', 50000 from dual union all
select 10, 'xxx', null from dual union all
select 10, 'ccc', 50000 from dual)
select empname, deptno, sal
     , rank() over (partition by deptno order by sal nulls first) r
     , dense_rank() over (partition by deptno order by sal nulls first) dr1
     , dense_rank() over (partition by deptno order by sal nulls last) dr2
 from q; 

EMP     DEPTNO        SAL          R        DR1        DR2
--- ---------- ---------- ---------- ---------- ----------
xxx         10                     1          1          4
rrr         10      10000          2          2          1
fff         10      40000          3          3          2
ddd         10      40000          3          3          2
ccc         10      50000          5          4          3
bbb         10      50000          5          4          3
mmm         11       5000          1          1          1
nnn         11      20000          2          2          2
kkk         12      30000          1          1          1

9 rows selected.

这里是一个很好的解释和一些例子的链接


14
一个很好的主意,是使用对偶选择全选来生成样本数据而无需创建任何表
Jean-Christophe Blanchard 2016年

@ Jean-ChristopheBlanchard,尽管您可以轻松使用values子句。
通配符

1
@Wildcard在PG中,是的。在Oracle中,。至少到11点为止,我还没有碰到12个。
jpmc26

from dual在Redshift
Gaurav

4
伊万(Ivan),RANK让我知道了相对于我之前的那些人,我在哪里。DENSE_RANK告诉我绝对排名。我的薪水可能第二高,但我前面可能有100个人。哪一个更好取决于我正在回答的问题。
DCookie

93

这篇文章很好地解释了它。本质上,您可以这样看:

CREATE TABLE t AS
SELECT 'a' v FROM dual UNION ALL
SELECT 'a'   FROM dual UNION ALL
SELECT 'a'   FROM dual UNION ALL
SELECT 'b'   FROM dual UNION ALL
SELECT 'c'   FROM dual UNION ALL
SELECT 'c'   FROM dual UNION ALL
SELECT 'd'   FROM dual UNION ALL
SELECT 'e'   FROM dual;

SELECT
  v,
  ROW_NUMBER() OVER (ORDER BY v) row_number,
  RANK()       OVER (ORDER BY v) rank,
  DENSE_RANK() OVER (ORDER BY v) dense_rank
FROM t
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() 为每一行赋予唯一值
  • RANK() 将相同的行号赋予相同的值,从而留下“漏洞”
  • DENSE_RANK() 将相同的行号赋予相同的值,不留“空洞”

错误:SQL错误:ORA-00923:在预期的位置找不到FROM关键字
zloctb

9
SELECT empno,
       deptno,
       sal,
       RANK() OVER (PARTITION BY deptno ORDER BY sal) "rank"
FROM   emp;

     EMPNO     DEPTNO        SAL       rank
---------- ---------- ---------- ----------
      7934         10       1300          1
      7782         10       2450          2
      7839         10       5000          3
      7369         20        800          1
      7876         20       1100          2
      7566         20       2975          3
      7788         20       3000          4
      7902         20       3000          4
      7900         30        950          1
      7654         30       1250          2
      7521         30       1250          2
      7844         30       1500          4
      7499         30       1600          5
      7698         30       2850          6


SELECT empno,
       deptno,
       sal,
       DENSE_RANK() OVER (PARTITION BY deptno ORDER BY sal) "rank"
FROM   emp;

     EMPNO     DEPTNO        SAL       rank
---------- ---------- ---------- ----------
      7934         10       1300          1
      7782         10       2450          2
      7839         10       5000          3
      7369         20        800          1
      7876         20       1100          2
      7566         20       2975          3
      7788         20       3000          4
      7902         20       3000          4
      7900         30        950          1
      7654         30       1250          2
      7521         30       1250          2
      7844         30       1500          3
      7499         30       1600          4
      7698         30       2850          5

8

rank():用于对一组行中的记录进行排名。

density_rank():DENSE_RANK函数的作用类似于RANK函数,只是它分配连续的等级。

查询-

select 
    ENAME,SAL,RANK() over (order by SAL) RANK
from 
    EMP;

输出-

+--------+------+------+
| ENAME  | SAL  | RANK |
+--------+------+------+
| SMITH  |  800 |    1 |
| JAMES  |  950 |    2 |
| ADAMS  | 1100 |    3 |
| MARTIN | 1250 |    4 |
| WARD   | 1250 |    4 |
| TURNER | 1500 |    6 |
+--------+------+------+

查询-

select 
    ENAME,SAL,dense_rank() over (order by SAL) DEN_RANK
from 
    EMP;

输出-

+--------+------+-----------+
| ENAME  | SAL  |  DEN_RANK |
+--------+------+-----------+
| SMITH  |  800 |         1 |
| JAMES  |  950 |         2 |
| ADAMS  | 1100 |         3 |
| MARTIN | 1250 |         4 |
| WARD   | 1250 |         4 |
| TURNER | 1500 |         5 |
+--------+------+-----------+

2
select empno
       ,salary
       ,row_number() over(order by salary desc) as Serial
       ,Rank() over(order by salary desc) as rank
       ,dense_rank() over(order by salary desc) as denseRank
from emp ;

Row_number() ->用于生成序列号

Dense_rank() 将给出连续的等级,但如果等级发生冲突,等级将跳过等级。


2

RANK()和DENSE_RANK()函数之间的唯一区别是存在“并列”的情况。也就是说,如果集合中的多个值具有相同的排名。在这种情况下,RANK()将不连续的“等级”分配给集合中的值(导致出现平局时导致整数排名值之间的间隔),而DENSE_RANK()将连续的等级分配给集合中的值设置(因此,在平局的情况下,整数排名值之间不会有间隙)。

例如,考虑集合{25,25,50,75,75,100}。对于这样的集合,RANK()将返回{1、1、3、4、4、6}(请注意,将跳过值2和5),而DENSE_RANK()将返回{1、2、3, 3,4}。


1

Rank()SQL函数生成数据在有序值集中的排名,但上一个排名之后的下一个排名是该特定行的row_number。另一方面,Dense_Rank()SQL函数将生成下一个数字,而不是生成row_number。以下是将阐明概念的SQL示例:

Select ROW_NUMBER() over (order by Salary) as RowNum, Salary, 
RANK() over (order by Salary) as Rnk, 
DENSE_RANK() over (order by Salary) as DenseRnk from (
Select 1000 as Salary union all
Select 1000 as Salary union all
Select 1000 as Salary union all
Select 2000 as Salary union all
Select 3000 as Salary union all
Select 3000 as Salary union all
Select 8000 as Salary union all
Select 9000 as Salary) A

它将生成以下输出:

----------------------------
RowNum  Salary  Rnk DenseRnk
----------------------------
1       1000    1   1
2       1000    1   1
3       1000    1   1
4       2000    4   2
5       3000    5   3
6       3000    5   3
7       8000    7   4
8       9000    8   5

0

等级和密集等级给出分区数据集中的等级。

Rank():它不会给您连续的整数。

Dense_rank():它为您提供连续的整数。

在此处输入图片说明

在上图中,考虑到row_number时,densed_rank()函数的10008 zip排名为2,rank()函数的排名为24。


0

Rank(), Dense_rank(), row_number() 这些都是窗口函数,这意味着它们首先充当某个有序输入集上的窗口。这些窗口根据需要具有附加的不同功能。这是上面的3:

row_number()

row_number()从这开始,就构成了这些相关窗口功能的基础。row_number()顾名思义,它为应用了该行的行集提供了唯一的编号。类似于为每一行提供序列号。

Rank()

的颠覆row_number()可以说是rank()。Rank()用于为重复的那些有序集行赋予相同的序列号,但row_number()对于所有在rank()之后重复的序号行,其计数仍保持与a相似,例如从下面开始。对于数据2 row_number()= rank(),这意味着两者的重复形式有所不同。

Data row_number() rank() dense_rank() 
    1         1                    1       1
    1         2                    1       1
    1         3                    1       1
    2         4                    4       2

最后,

Dense_rank()是rank()的扩展版本,顾名思义,它是致密的,因为如上例所示,对于所有数据1,rank()= density_rank()只是对数据2而言,它的形式有所不同从先前的rank()保留rank()的顺序,而不是实际数据


0

RANK()和DENSE_RANK()函数之间的唯一区别是存在“并列”的情况。也就是说,如果集合中的多个值具有相同的排名。在这种情况下,RANK()将不连续的“等级”分配给集合中的值(导致出现平局时导致整数排名值之间的间隔),而DENSE_RANK()将连续的等级分配给集合中的值设置(因此,在平局的情况下,整数排名值之间不会有间隙)。

例如,考虑集合{30,30,50,75,75,100}。对于这样的集合,RANK()将返回{1、1、3、4、4、6}(请注意,将跳过值2和5),而DENSE_RANK()将返回{1、2、3, 3,4}。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.