Was ist der Unterschied zwischen den Funktionen RANK () und DENSE_RANK () in Oracle?


150

Was ist der Unterschied zwischen RANK()und DENSE_RANK()Funktionen? Wie finde ich das n-te Gehalt in der folgenden emptblTabelle heraus?

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 Tabelle Daten vorhanden sind nulls, was passiert, wenn ich das nthGehalt herausfinden möchte ?

Antworten:


242

RANK gibt Ihnen das Ranking innerhalb Ihrer bestellten Partition. Krawatten erhalten den gleichen Rang, wobei die nächsten Ränge übersprungen werden. Wenn Sie also 3 Gegenstände auf Rang 2 haben, wird der nächste aufgeführte Rang auf Rang 5 gesetzt.

DENSE_RANK gibt Ihnen erneut das Ranking innerhalb Ihrer geordneten Partition, aber die Ränge sind aufeinanderfolgend. Es werden keine Ränge übersprungen, wenn Ränge mit mehreren Elementen vorhanden sind.

Nullen hängen von der ORDER BY-Klausel ab. Hier ist ein einfaches Testskript, mit dem Sie 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.

Hier ist ein Link zu einer guten Erklärung und einigen Beispielen.


14
Sehr gute Idee, Select Union All aus Dual zu verwenden, um Beispieldaten zu generieren, ohne eine Tabelle zu erstellen
Jean-Christophe Blanchard

@ Jean-ChristopheBlanchard, obwohl Sie genauso gut eine valuesKlausel 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

Entfernen Sie from dualfür die Generierung dieser Daten in Redshift
Gaurav

4
Ivan, RANK gibt mir eine Idee, wo ich relativ zu all denen bin, die vor mir liegen. DENSE_RANK sagt mir den absoluten Rang. Ich habe vielleicht das zweithöchste Gehalt, aber es könnten 100 Leute vor mir sein. Welches besser ist, hängt von der Frage ab, die ich beantworte.
DCookie

93

Dieser Artikel hier erklärt es schön. Im Wesentlichen können Sie es als solches betrachten:

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;

Das Obige ergibt:

+---+------------+------+------------+
| 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() weist jeder Zeile einen eindeutigen Wert zu
  • RANK() schreibt dem gleichen Wert dieselbe Zeilennummer zu und hinterlässt "Löcher"
  • DENSE_RANK() schreibt dem gleichen Wert dieselbe Zeilennummer zu und hinterlässt keine "Löcher"

Fehler: SQL-Fehler: ORA-00923: FROM-Schlüsselwort nicht gefunden, wo erwartet
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 () : Wird verwendet, um einen Datensatz innerhalb einer Gruppe von Zeilen zu ordnen.

dens_rank () : Die DENSE_RANK-Funktion verhält sich wie die RANK-Funktion, weist jedoch aufeinanderfolgende Ränge zu.

Abfrage -

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

Ausgabe -

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

Ausgabe -

+--------+------+-----------+
| 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() -> Wird zur Generierung der Seriennummer verwendet

Dense_rank() gibt einen kontinuierlichen Rang, aber der Rang überspringt den Rang im Falle eines Rangkonflikts.


2

Der einzige Unterschied zwischen den Funktionen RANK () und DENSE_RANK () besteht in Fällen, in denen ein „Gleichstand“ besteht. dh in Fällen, in denen mehrere Werte in einem Satz dieselbe Rangfolge haben. In solchen Fällen weist RANK () den Werten in der Menge nicht aufeinanderfolgende „Ränge“ zu (was zu Lücken zwischen den ganzzahligen Rangwerten führt, wenn ein Gleichstand besteht), während DENSE_RANK () den Werten in der Gruppe aufeinanderfolgende Ränge zuweist set (so dass es bei einem Gleichstand keine Lücken zwischen den ganzzahligen Rangwerten gibt).

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


1

Rank () Die SQL-Funktion generiert den Rang der Daten innerhalb des geordneten Wertesatzes, aber der nächste Rang nach dem vorherigen Rang ist row_number dieser bestimmten Zeile. Andererseits generiert die SQL-Funktion Dense_Rank () die nächste Nummer, anstatt row_number zu generieren. Unten finden Sie das SQL-Beispiel, das das Konzept verdeutlicht:

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

Es wird folgende Ausgabe generiert:

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

Rang und dichter Rang geben den Rang im partitionierten Datensatz an.

Rank (): Es gibt keine aufeinanderfolgenden Ganzzahlen.

Dense_rank (): Sie erhalten aufeinanderfolgende Ganzzahlen.

Geben Sie hier die Bildbeschreibung ein

Im obigen Bild beträgt der Rang von 10008 zip 2 nach der Funktion dens_rank () und 24 nach der Funktion rank (), wenn die Zeilennummer berücksichtigt wird.


0

Rank(), Dense_rank(), row_number() Dies sind alles Fensterfunktionen, dh sie fungieren zunächst als Fenster über einem geordneten Eingabesatz. Diesen Fenstern sind je nach Anforderung unterschiedliche Funktionen zugeordnet. Hier ist die obige 3:

row_number()

Ausgehend row_number()davon bildet dies die Grundlage für diese zugehörigen Fensterfunktionen. row_number()Wie der Name schon sagt, gibt der Satz von Zeilen, auf die er angewendet wurde, eine eindeutige Nummer. Ähnlich wie bei der Angabe einer Seriennummer für jede Zeile.

Rank()

Eine Subversion von row_number()kann gesagt werden als rank(). Rank () wird verwendet, um den geordneten Satzreihen, bei denen es sich um Duplikate handelt, dieselbe Seriennummer zu geben. Die Anzahl wird jedoch weiterhin als ähnlich zu a row_number()für alle nach Duplikaten gehalten. Rank () bedeutet wie von unten, z. Für Daten 2 bedeutet row_number () = rank (), dass sich beide nur in Form von Duplikaten unterscheiden.

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

Schließlich,

Dense_rank () ist eine erweiterte Version von rank (), wie der Name andeutet, denn wie Sie aus dem obigen Beispiel ersehen können, unterscheidet sich rank () = dens_rank () für alle Daten 1, aber nur für Daten 2 in der Form, in der es sich befindet behält die Reihenfolge von Rang () vom vorherigen Rang () bei, nicht die tatsächlichen Daten


0

Der einzige Unterschied zwischen den Funktionen RANK () und DENSE_RANK () besteht in Fällen, in denen ein „Gleichstand“ besteht. dh in Fällen, in denen mehrere Werte in einem Satz dieselbe Rangfolge haben. In solchen Fällen weist RANK () den Werten in der Menge nicht aufeinanderfolgende „Ränge“ zu (was zu Lücken zwischen den ganzzahligen Rangwerten führt, wenn ein Gleichstand besteht), während DENSE_RANK () den Werten in der Gruppe aufeinanderfolgende Ränge zuweist set (so dass es bei einem Gleichstand keine Lücken zwischen den ganzzahligen Rangwerten gibt).

Betrachten Sie beispielsweise die Menge {30, 30, 50, 75, 75, 100}. Für eine solche Menge gibt RANK () {1, 1, 3, 4, 4, 6} zurück (beachten Sie, dass die Werte 2 und 5 übersprungen werden), während DENSE_RANK () {1,1,2,3, 3,4}.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.