Qual é a diferença entre as funções RANK () e DENSE_RANK () no oracle?


150

Qual a diferença entre RANK()e DENSE_RANK()funções? Como descobrir o enésimo salário na emptbltabela a seguir ?

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

Se nos dados da tabela nulls, o que acontecerá se eu quiser descobrir o nthsalário?

Respostas:


242

RANK fornece a classificação na partição ordenada. Os empates recebem a mesma classificação, com o (s) próximo (s) ranking (s) ignorado (s). Portanto, se você tiver 3 itens na classificação 2, a próxima classificação listada será classificada como 5.

DENSE_RANK novamente fornece a classificação na partição ordenada, mas as classificações são consecutivas. Nenhuma classificação será ignorada se houver classificações com vários itens.

Quanto aos nulos, isso depende da cláusula ORDER BY. Aqui está um script de teste simples com o qual você pode jogar para ver o que acontece:

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.

Aqui está um link para uma boa explicação e alguns exemplos.


14
muito boa idéia usar select união todos da dupla para gerar dados amostra sem criar qualquer tabela
Jean-Christophe Blanchard

@ Jean-ChristopheBlanchard, embora você possa usar com facilidade uma valuescláusula.
Curinga

1
@Wildcard No PG, sim. No Oracle, não . Pelo menos não a partir de 11. Ainda não encontrei 12 em prod.
Jpmc26

Remova from dualpara gerar esses dados em Redshift
Gaurav

4
Ivan, RANK, me dá uma idéia de onde estou em relação a todos aqueles à minha frente. DENSE_RANK me diz a classificação absoluta. Posso ter o segundo salário mais alto, mas pode haver 100 pessoas à minha frente. Qual é o melhor depende da pergunta que estou respondendo.
DCookie

93

Este artigo aqui explica bem. Essencialmente, você pode olhar para isso da seguinte forma:

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;

O acima irá render:

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

Em palavras

  • ROW_NUMBER() atribui um valor exclusivo a cada linha
  • RANK() atribui o mesmo número de linha ao mesmo valor, deixando "buracos"
  • DENSE_RANK() atribui o mesmo número de linha ao mesmo valor, não deixando "buracos"

Erro: Erro SQL: Palavra-chave ORA-00923: FROM não encontrada onde o esperado
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 () : é usado para classificar um registro dentro de um grupo de linhas.

dense_rank () : A função DENSE_RANK atua como a função RANK, exceto pelo fato de atribuir classificações consecutivas.

Inquerir -

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

Resultado -

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

Inquerir -

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

Resultado -

+--------+------+-----------+
| 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() -> Usado para gerar número de série

Dense_rank() dará classificação contínua, mas a classificação pulará a classificação em caso de conflito de classificação.


2

A única diferença entre as funções RANK () e DENSE_RANK () ocorre nos casos em que há um "empate"; ou seja, nos casos em que vários valores em um conjunto têm a mesma classificação. Nesses casos, RANK () atribuirá "classificações" não consecutivas aos valores do conjunto (resultando em intervalos entre os valores de classificação inteira quando houver um empate), enquanto DENSE_RANK () atribuirá classificações consecutivas aos valores no conjunto. definido (portanto, não haverá lacunas entre os valores de classificação inteira no caso de empate).

Por exemplo, considere o conjunto {25, 25, 50, 75, 75, 100}. Para esse conjunto, RANK () retornará {1, 1, 3, 4, 4, 6} (observe que os valores 2 e 5 são ignorados), enquanto DENSE_RANK () retornará {1,1,2,3, 3,4}.


1

A função Rank () SQL gera a classificação dos dados dentro do conjunto ordenado de valores, mas a próxima classificação após a classificação anterior é o número da linha dessa linha específica. Por outro lado, a função SQL Dense_Rank () gera o próximo número em vez de gerar o número da linha. Abaixo está o exemplo do SQL que esclarecerá o conceito:

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

Ele irá gerar a seguinte saída:

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

Classificação e classificação densa fornecem a classificação no conjunto de dados particionado.

Rank (): não fornece números inteiros consecutivos.

Dense_rank (): fornece números inteiros consecutivos.

insira a descrição da imagem aqui

Na figura acima, a classificação de 10008 zip é 2 pela função dense_rank () e 24 pela função rank (), pois considera o número da linha.


0

Rank(), Dense_rank(), row_number() Todas essas são funções de janela, o que significa que agem como janela sobre algumas entradas ordenadas definidas no início. Essas janelas têm funcionalidades diferentes anexadas, com base no requisito. Aqui está o acima 3:

row_number()

Começando por row_number()isso, forma a base dessas funções de janela relacionadas. row_number()como o nome sugere, fornece um número exclusivo para o conjunto de linhas sobre as quais foi aplicado. É semelhante a atribuir um número de série a cada linha.

Rank()

Uma subversão de row_number()pode ser dita como rank(). Rank () é usado para atribuir o mesmo número de série às linhas de conjunto ordenadas que são duplicadas, mas ainda mantém a contagem mantida como semelhante a row_number()para todos aqueles depois de duplicatas, o que significa abaixo, por exemplo. Para os dados 2 row_number () = rank (), o que significa que ambos diferem apenas na forma de duplicatas.

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 () é uma versão estendida de rank (), pois o nome sugere sua densidade, porque, como você pode ver no exemplo acima, rank () = dense_rank () para todos os dados 1, mas apenas para os dados 2, ele difere na forma em que mantém a ordem da classificação () da classificação anterior () e não os dados reais


0

A única diferença entre as funções RANK () e DENSE_RANK () ocorre nos casos em que há um "empate"; ou seja, nos casos em que vários valores em um conjunto têm a mesma classificação. Nesses casos, RANK () atribuirá "classificações" não consecutivas aos valores do conjunto (resultando em intervalos entre os valores de classificação inteira quando houver um empate), enquanto DENSE_RANK () atribuirá classificações consecutivas aos valores no conjunto. definido (portanto, não haverá lacunas entre os valores de classificação inteira no caso de empate).

Por exemplo, considere o conjunto {30, 30, 50, 75, 75, 100}. Para esse conjunto, RANK () retornará {1, 1, 3, 4, 4, 6} (observe que os valores 2 e 5 são ignorados), enquanto DENSE_RANK () retornará {1,1,2,3, 3,4}.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.