Quelle est la différence entre les fonctions RANK () et DENSE_RANK () dans oracle?


150

Quelle est la différence entre RANK()et DENSE_RANK()fonctions? Comment connaître le nième salaire dans le emptbltableau suivant ?

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

Si dans le tableau les données ont nulls, que se passera-t-il si je veux connaître le nthsalaire?

Réponses:


242

RANK vous donne le classement dans votre partition ordonnée. Les égalités sont attribuées au même rang, le (s) classement (s) suivant (s) étant ignoré (s). Donc, si vous avez 3 éléments au rang 2, le rang suivant sera classé 5.

DENSE_RANK vous donne à nouveau le classement dans votre partition ordonnée, mais les rangs sont consécutifs. Aucun classement n'est ignoré s'il existe des rangs avec plusieurs éléments.

Quant aux valeurs nulles, cela dépend de la clause ORDER BY. Voici un script de test simple avec lequel vous pouvez jouer pour voir ce qui se passe:

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.

Voici un lien vers une bonne explication et quelques exemples.


14
très bonne idée d'utiliser select union all from dual pour générer des exemples de données sans créer de table
Jean-Christophe Blanchard

@ Jean-ChristopheBlanchard bien que vous puissiez tout aussi bien utiliser une valuesclause.
Wildcard

1
@Wildcard Dans PG, oui. Dans Oracle, non . Du moins pas à partir de 11. Je n'ai pas encore rencontré 12 en prod.
jpmc26

Supprimer from dualpour générer ces données dans Redshift
Gaurav

4
Ivan, RANK me donne une idée où je suis par rapport à tous ceux qui m'attendent. DENSE_RANK me donne le rang absolu. J'ai peut-être le deuxième salaire le plus élevé, mais il pourrait y avoir 100 personnes devant moi. Lequel est le meilleur dépend de la question à laquelle je réponds.
DCookie

93

Cet article ici l'explique bien. Essentiellement, vous pouvez le regarder comme tel:

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;

Ce qui précède donnera:

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

Dans les mots

  • ROW_NUMBER() attribue une valeur unique à chaque ligne
  • RANK() attribue le même numéro de ligne à la même valeur, laissant des "trous"
  • DENSE_RANK() attribue le même numéro de ligne à la même valeur, sans laisser de "trous"

Erreur: Erreur SQL: ORA-00923: mot clé FROM introuvable à l'endroit prévu
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 () : il est utilisé pour classer un enregistrement dans un groupe de lignes.

dense_rank () : La fonction DENSE_RANK agit comme la fonction RANK sauf qu'elle attribue des rangs consécutifs.

Requete -

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

Production -

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

Requete -

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

Production -

+--------+------+-----------+
| 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() -> Utilisé pour générer le numéro de série

Dense_rank() donnera un rang continu mais le rang sautera le rang en cas de conflit de rang.


2

La seule différence entre les fonctions RANK () et DENSE_RANK () est dans les cas où il y a une «égalité»; c'est-à-dire dans les cas où plusieurs valeurs dans un ensemble ont le même classement. Dans de tels cas, RANK () attribuera des «rangs» non consécutifs aux valeurs de l'ensemble (ce qui entraînera des écarts entre les valeurs de classement entier en cas d'égalité), tandis que DENSE_RANK () attribuera des rangs consécutifs aux valeurs du set (il n'y aura donc aucun écart entre les valeurs de classement entier en cas d'égalité).

Par exemple, considérons l'ensemble {25, 25, 50, 75, 75, 100}. Pour un tel ensemble, RANK () retournera {1, 1, 3, 4, 4, 6} (notez que les valeurs 2 et 5 sont ignorées), alors que DENSE_RANK () retournera {1,1,2,3, 3,4}.


1

La fonction SQL Rank () génère le rang des données dans un ensemble ordonné de valeurs, mais le rang suivant après le rang précédent est row_number de cette ligne particulière. D'autre part, la fonction SQL Dense_Rank () génère le numéro suivant au lieu de générer row_number. Voici l'exemple SQL qui clarifiera le concept:

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

Il générera la sortie suivante:

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

Rank and Dense rank donne le rang dans l'ensemble de données partitionné.

Rank (): Il ne vous donne pas de nombres entiers consécutifs.

Dense_rank (): Il vous donne des nombres entiers consécutifs.

entrez la description de l'image ici

Dans l'image ci-dessus, le rang de 10008 zip est 2 par la fonction dense_rank () et 24 par la fonction rank () car il considère le row_number.


0

Rank(), Dense_rank(), row_number() Ce sont toutes des fonctions de fenêtre, ce qui signifie qu'elles agissent comme une fenêtre sur un ensemble d'entrées ordonnées au début. Ces fenêtres ont différentes fonctionnalités attachées en fonction de l'exigence. Voici les 3 ci-dessus:

row_number()

En commençant par row_number()car cela constitue la base de ces fonctions de fenêtre associées. row_number()comme son nom l'indique, donne un numéro unique à l'ensemble de lignes sur lequel il a été appliqué. Similaire à donner un numéro de série à chaque ligne.

Rank()

Une subversion de row_number()peut être dite comme rank(). Rank () est utilisé pour donner le même numéro de série à ces lignes d'ensemble ordonnées qui sont des doublons, mais il garde toujours le compte maintenu comme similaire à a row_number()pour tous ceux après les doublons. Pour les données 2 row_number () = rank () signifiant que les deux diffèrent simplement sous la forme de doublons.

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

Finalement,

Dense_rank () est une version étendue de rank () comme son nom l'indique, c'est dense parce que comme vous pouvez le voir dans l'exemple ci-dessus rank () = dense_rank () pour toutes les données 1 mais juste que pour les données 2, il diffère sous la forme conserve l'ordre de rang () à partir du rang précédent () et non les données réelles


0

La seule différence entre les fonctions RANK () et DENSE_RANK () est dans les cas où il y a une «égalité»; c'est-à-dire dans les cas où plusieurs valeurs dans un ensemble ont le même classement. Dans de tels cas, RANK () attribuera des «rangs» non consécutifs aux valeurs de l'ensemble (ce qui entraînera des écarts entre les valeurs de classement entier en cas d'égalité), tandis que DENSE_RANK () attribuera des rangs consécutifs aux valeurs du set (il n'y aura donc aucun écart entre les valeurs de classement entier en cas d'égalité).

Par exemple, considérons l'ensemble {30, 30, 50, 75, 75, 100}. Pour un tel ensemble, RANK () retournera {1, 1, 3, 4, 4, 6} (notez que les valeurs 2 et 5 sont ignorées), alors que DENSE_RANK () retournera {1,1,2,3, 3,4}.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.