2012-06-25 7 views
85

Was ist der Unterschied zwischen RANK() und DENSE_RANK() Funktionen? Wie finde ich Nth Gehalt in der folgenden emptbl Tabelle?Was ist der Unterschied zwischen den Funktionen RANK() und DENSE_RANK() in Oracle?

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 

Wenn in der Datentabelle nulls mit, was passiert, wenn ich nth Gehalt herausfinden wollen?

Antwort

146

RANK gibt Ihnen das Ranking innerhalb Ihrer bestellten Partition. Ties erhalten den gleichen Rang, wobei die nächste (n) Rangfolge (n) übersprungen werden. Also, wenn Sie 3 Punkte auf Rang 2 haben, wäre der nächste Rang Rang 5.

DENSE_RANK gibt Ihnen wieder das Ranking innerhalb Ihrer geordneten Partition, aber die Ränge sind aufeinander folgend. Wenn es Ränge mit mehreren Elementen gibt, werden keine Ränge übersprungen.

Wie bei Nullen hängt es von der ORDER BY-Klausel ab. Hier ist ein einfaches Testskript Sie mit spielen können, um zu sehen, was passiert:

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 auf eine gute Erklärung und einige Beispiele.

+6

sehr gut id ea, um die Auswahl union all from dual zu verwenden, um Beispieldaten zu erzeugen, ohne eine Tabelle zu erstellen. –

+0

@ Jean-ChristopheBlanchard obwohl Sie genauso gut eine 'values'-Klausel verwenden könnten. – Wildcard

+1

@Wildcard In PG ja. In Oracle, * nein *. Zumindest nicht ab 11. Ich bin noch nicht auf 12 in prod gestoßen. – 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() -> Wird für die Seriennummer zu erzeugen

Dense_rank() wird kontinuierlich Rang geben, aber Rang wird Rang bei Zusammenstoß von Rang überspringen.

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. Im Wesentlichen kann man es als solche aussehen:

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; 

Die oben nachgeben:

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

In Worten

  • ROW_NUMBER() Attribute einen eindeutigen Wert zu jeder Reihe
  • RANK() Attribute die gleiche Zeilennummer auf denselben Wert, „Löcher“
  • DENSE_RANK() Attribute die gleiche Zeilennummer auf den gleichen Wert zu verlassen,
+1

Das ist so gut :) – nanosoft

+0

Fehler: SQL Fehler: ORA-00923: FROM Schlüsselwort nicht gefunden, wo erwartet – zloctb

+0

@zloctb: Ja, danke. Fest –

1

Der einzige Unterschied zwischen der RANK keine „Löcher“ leaving () und DENSE_RANK() Funktionen ist in Fällen, in denen es eine "Krawatte" gibt; h. in Fällen, in denen mehrere Werte in einem Satz die gleiche Rangfolge haben. In solchen Fällen ordnet RANK() den Werten in der Menge nicht aufeinanderfolgende "Ränge" zu (was zu Lücken zwischen den ganzzahligen Rangfolgenwerten führt, wenn eine Bindung besteht), während DENSE_RANK() den Rängen in der Tabelle fortlaufende Ränge zuweisen wird setzen (so wird es keine Lücken zwischen den Integer-Ranking-Werten im Falle eines Unentschiedens geben).

Betrachten Sie zum Beispiel die Menge {25, 25, 50, 75, 75, 100}. Für eine solche Menge liefert RANK() {1, 1, 3, 4, 4, 6} (beachten Sie, dass die Werte 2 und 5 übersprungen werden), während DENSE_RANK() {1,1,2,3, 3,4}.

2

rank(): Es wird verwendet, um einen Datensatz innerhalb einer Gruppe von Zeilen zu sortieren.

dese_rank(): Die DENSE_RANK-Funktion verhält sich wie die RANK-Funktion, außer dass sie aufeinanderfolgende Ränge zuweist.

Abfrage -

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

Ausgang -

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

Abfrage -

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

Ausgang -

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