¿Cuál es la diferencia entre las funciones RANK () y DENSE_RANK () en Oracle?


150

¿Cuál es la diferencia entre RANK()y DENSE_RANK()funciones? ¿Cómo averiguar el enésimo salario en la siguiente emptbltabla?

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 en la tabla hay datos nulls, ¿qué pasará si quiero saber el nthsalario?

Respuestas:


242

RANK le da la clasificación dentro de su partición ordenada. A los empates se les asigna el mismo rango, y se omiten las siguientes clasificaciones. Entonces, si tiene 3 artículos en el rango 2, el siguiente rango en la lista sería el 5.

DENSE_RANK nuevamente le da la clasificación dentro de su partición ordenada, pero los rangos son consecutivos. No se omiten los rangos si hay rangos con varios elementos.

En cuanto a los nulos, depende de la cláusula ORDER BY. Aquí hay un script de prueba simple con el que puedes jugar para ver qué sucede:

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.

Aquí hay un enlace a una buena explicación y algunos ejemplos.


14
muy buena idea usar select union all from dual para generar datos de muestra sin crear ninguna tabla
Jean-Christophe Blanchard

@ Jean-ChristopheBlanchard, aunque podría usar fácilmente una valuescláusula.
Comodín el

1
@Wildcard En PG, sí. En Oracle, no . Al menos no a partir de 11. Todavía no me he encontrado con 12 en productos.
jpmc26

Eliminar from dualpara generar estos datos en Redshift
Gaurav

44
Ivan, RANK me da una idea de dónde estoy en relación con todos los que están delante de mí. DENSE_RANK me dice el rango absoluto. Puede que tenga el segundo salario más alto, pero podría haber 100 personas por delante. Cuál es mejor depende de la pregunta que estoy respondiendo.
DCookie

93

Este artículo aquí lo explica muy bien. Esencialmente, puedes verlo como tal:

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;

Lo anterior producirá:

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

En palabras

  • ROW_NUMBER() atribuye un valor único a cada fila
  • RANK() atribuye el mismo número de fila al mismo valor, dejando "agujeros"
  • DENSE_RANK() atribuye el mismo número de fila al mismo valor, sin dejar "agujeros"

Error: Error SQL: ORA-00923: no se encontró la palabra clave FROM donde se esperaba
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 () : se utiliza para clasificar un registro dentro de un grupo de filas.

dense_rank () : la función DENSE_RANK actúa como la función RANK, excepto que asigna rangos consecutivos.

Consulta -

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

Salida -

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

Consulta -

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

Salida -

+--------+------+-----------+
| 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() -> Utilizado para generar número de serie

Dense_rank() dará un rango continuo pero el rango saltará el rango en caso de choque de rango.


2

La única diferencia entre las funciones RANK () y DENSE_RANK () es en los casos en que hay un "empate"; es decir, en casos donde múltiples valores en un conjunto tienen la misma clasificación. En tales casos, RANK () asignará "rangos" no consecutivos a los valores del conjunto (lo que dará como resultado brechas entre los valores de clasificación de enteros cuando haya un empate), mientras que DENSE_RANK () asignará rangos consecutivos a los valores en el set (por lo que no habrá espacios entre los valores de clasificación de enteros en el caso de un empate).

Por ejemplo, considere el conjunto {25, 25, 50, 75, 75, 100}. Para tal conjunto, RANK () devolverá {1, 1, 3, 4, 4, 6} (tenga en cuenta que los valores 2 y 5 se omiten), mientras que DENSE_RANK () devolverá {1,1,2,3, 3,4}.


1

La función SQL Rank () genera el rango de los datos dentro del conjunto ordenado de valores, pero el siguiente rango después del rango anterior es row_number de esa fila en particular. Por otro lado, la función Dense_Rank () SQL genera el siguiente número en lugar de generar row_number. A continuación se muestra el ejemplo de SQL que aclarará el concepto:

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

Generará el siguiente resultado:

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

Rango y Rango denso da el rango en el conjunto de datos particionado.

Rango (): no te da números enteros consecutivos.

Dense_rank (): te da números enteros consecutivos.

ingrese la descripción de la imagen aquí

En la imagen de arriba, el rango de 10008 zip es 2 por función dense_rank () y 24 por rango (), ya que considera el número de fila.


0

Rank(), Dense_rank(), row_number() Todas estas son funciones de ventana, lo que significa que actúan como ventana sobre un conjunto de entradas ordenadas al principio. Estas ventanas tienen una funcionalidad diferente asociada según el requisito. Heres los 3 anteriores:

row_number()

Comenzando por row_number()esto forma la base de estas funciones de ventana relacionadas. row_number()como su nombre lo indica, da un número único al conjunto de filas sobre el que se ha aplicado. Similar a dar un número de serie a cada fila.

Rank()

Una subversión de row_number()se puede decir como rank(). Rank () se usa para dar el mismo número de serie a las filas ordenadas del conjunto que son duplicados, pero aún mantiene el recuento mantenido como similar a un row_number()para todos aquellos después de duplicar el significado de rank (), como se muestra a continuación, por ejemplo. Para los datos 2 row_number () = rank (), lo que significa que ambos difieren en forma de duplicados.

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

Finalmente,

Dense_rank () es una versión extendida de rank () ya que el nombre sugiere que es denso porque, como puede ver en el ejemplo anterior, rank () = dense_rank () para todos los datos 1 pero solo para los datos 2 difiere en la forma en que mantiene el orden de rango () del rango anterior () no los datos reales


0

La única diferencia entre las funciones RANK () y DENSE_RANK () es en los casos en que hay un "empate"; es decir, en casos donde múltiples valores en un conjunto tienen la misma clasificación. En tales casos, RANK () asignará "rangos" no consecutivos a los valores del conjunto (lo que dará como resultado brechas entre los valores de clasificación de enteros cuando haya un empate), mientras que DENSE_RANK () asignará rangos consecutivos a los valores en el set (por lo que no habrá espacios entre los valores de clasificación de enteros en el caso de un empate).

Por ejemplo, considere el conjunto {30, 30, 50, 75, 75, 100}. Para tal conjunto, RANK () devolverá {1, 1, 3, 4, 4, 6} (tenga en cuenta que los valores 2 y 5 se omiten), mientras que DENSE_RANK () devolverá {1,1,2,3, 3,4}.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.