2012-06-25 106 views
85

RANK()DENSE_RANK()功能有什么区别?如何在以下emptbl表中找出第n个工资?oracle中的RANK()和DENSE_RANK()函数有什么区别?

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薪水是多少?

回答

146

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. 

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

+6

很好ID ea使用select中的select all union生成示例数据,但不创建任何表格 –

+0

@ Jean-ChristopheBlanchard,尽管您可以轻松使用“values”子句。 – Wildcard

+1

@Wildcard在PG中,是的。在Oracle中,* no *。至少不是11.我还没有碰到12。 – jpmc26

1
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()会给连续秩但秩将秩的冲突的情况下,跳过秩。

6
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 
54

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()属性相同的行数为相同的值,留下“洞”
  • DENSE_RANK()属性相同的行数为相同的值,不会留下任何的“洞”
+1

这很好:) – nanosoft

+0

错误:SQL错误:ORA-00923:从预期的关键字中找不到 – zloctb

+0

@zloctb:是的,谢谢。固定 –

1

的RANK之间唯一的差别( )和DENSE_RANK()函数在有“tie”的情况下;即在一组中的多个值具有相同排名的情况下。在这种情况下,RANK()会为集合中的值分配不连续的“等级”(当存在并列时,导致整数排列值之间存在差距),而DENSE_RANK()会将连续等级分配给设置(所以在并列情况下,整数排名值之间不会有差距)。

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

2

秩():它用于排序的一组行内的记录。

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

查询 -

​​

输出 -

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