2012-06-25 25 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 | 
+--------+------+-----------+ 
相關問題