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

时间:2012-06-25 04:35:26

标签: sql oracle window-functions

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薪水会怎样?

10 个答案:

答案 0 :(得分:203)

RANK为您提供订购分区内的排名。领带被分配相同的排名,跳过下一个排名。因此,如果您在排名2中有3个项目,则列出的下一个排名将排​​名为5.

DENSE_RANK再次为您提供有序分区内的排名,但排名是连续的。如果有多个项目的排名,则不会跳过任何排名。

对于null,它取决于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.

Here's a link给出了一个很好的解释和一些例子。

答案 1 :(得分:77)

This article here nicely explains it.基本上,你可以这样看:

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()将相同的行号归为相同的值,留下“holes”
  • DENSE_RANK()将相同的行号归属为相同的值,不留任何“漏洞”

答案 2 :(得分: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

答案 3 :(得分:6)

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

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

答案 4 :(得分: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()会给出持续排名但排名会在排名冲突的情况下跳过排名。

答案 5 :(得分:2)

RANK()和DENSE_RANK()函数之间的唯一区别是存在“平局”;即,在集合中的多个值具有相同排名的情况下。在这种情况下,RANK()会为集合中的值分配非连续的“排名”(当存在平局时导致整数排名值之间的差距),而DENSE_RANK()将连续排名分配给set(因此在平局的情况下,整数排名值之间不会有间隙)。

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

答案 6 :(得分: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

答案 7 :(得分:0)

Rank and Dense rank给出了分区数据集中的排名。

Rank():它不会为您提供连续的整数。

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

enter image description here

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

答案 8 :(得分:0)

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

row_number()

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

Rank()

row_number()的颠覆可以称为rank()。 Rank()用于为重复的那些有序集行赋予相同的序列号,但对于在rank()之后重复的所有行,仍然保持与row_number()类似的计数,这是从下面开始的。对于数据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()顺序的形式

答案 9 :(得分: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}。