오라클에서 RANK ()와 DENSE_RANK () 함수의 차이점은 무엇입니까?


150

차이 무엇 RANK()DENSE_RANK()기능은? 다음 emptbl표 에서 n 번째 급여를 찾는 방법은 무엇입니까?

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

표 데이터에 nulls가있는 경우 nth급여 를 찾으려면 어떻게됩니까?

답변:


242

RANK는 주문한 파티션 내 순위를 제공합니다. 동점에는 동일한 순위가 할당되며 다음 순위는 건너 뜁니다. 따라서 순위 2에 3 개의 항목이 있으면 다음 순위가 5가됩니다.

DENSE_RANK는 다시 주문 파티션 내의 순위를 제공하지만 순위는 연속적입니다. 여러 항목이있는 순위가 있으면 순위를 건너 뛰지 않습니다.

널은 ORDER BY 절에 따라 다릅니다. 다음은 간단한 테스트 스크립트로 어떤 일이 발생하는지 확인할 수 있습니다.

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.

다음 은 좋은 설명과 몇 가지 예에 대한 링크 입니다.


14
테이블을 만들지 않고 샘플 데이터를 생성하기 위해 이중에서 select union을 모두 사용하는 것이 좋습니다.
Jean-Christophe Blanchard

@ Jean-ChristopheBlanchard를 사용하면 values절 을 쉽게 사용할 수 있습니다 .
와일드 카드

1
@Wildcard PG에서는 가능합니다. Oracle에서는 아니요 . 적어도 11 일 현재는 아닙니다. 나는 아직 12에 빠지지 않았습니다.
jpmc26

제거 from dualRedshift에이 데이터를 생성
Gaurav

4
이반, RANK는 저보다 앞서있는 모든 사람들과 내가 어느 곳에 있는지 알고 있습니다. DENSE_RANK는 절대 순위를 알려줍니다. 나는 두 번째로 높은 급여를받을 수 있지만, 나보다 100 명이 앞서있을 수 있습니다. 어느 쪽이 더 좋은지는 내가 대답하는 질문에 달려 있습니다.
DCookie

93

이 기사는 여기에 잘 설명되어 있습니다. 기본적으로 다음과 같이 볼 수 있습니다.

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;

위의 결과는 다음과 같습니다.

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

말로

  • ROW_NUMBER() 각 행에 고유 한 값을 부여
  • RANK() "구멍"을 남기고 동일한 행 번호를 동일한 값으로 속성 지정
  • DENSE_RANK() "구멍"을 남기지 않고 동일한 행 번호를 동일한 값으로 속성 지정

오류 : SQL 오류 : ORA-00923 : FROM 키워드를 찾을 수 없습니다
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 () : 행 그룹 내에서 레코드 순위를 지정하는 데 사용됩니다.

dense_rank () : DENSE_RANK 함수는 연속 순위를 할당한다는 점을 제외하고는 RANK 함수처럼 작동합니다.

검색어-

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

출력-

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

검색어-

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

출력-

+--------+------+-----------+
| 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() -> 일련 번호 생성에 사용

Dense_rank() 연속 순위를 제공하지만 순위 충돌의 경우 순위를 건너 뜁니다.


2

RANK ()와 DENSE_RANK () 함수의 유일한 차이점은 "tie"가있는 경우입니다. 즉, 집합의 여러 값이 동일한 순위를 갖는 경우입니다. 이러한 경우 RANK ()는 비 연속적인 "순위"를 세트의 값에 지정하고 (타이가있을 때 정수 순위 값 사이의 간격이 발생 함) DENSE_RANK ()는 설정 (따라서 동점 인 경우 정수 순위 값 사이에 간격이 없음).

예를 들어, {25, 25, 50, 75, 75, 100} 세트를 고려하십시오. 이러한 세트의 경우 RANK ()는 {1, 1, 3, 4, 4, 6}을 리턴하고 (값 2와 5는 생략 됨) DENSE_RANK ()는 {1,1,2,3을 리턴합니다. 3,4}.


1

Rank () SQL 함수는 정렬 된 값 세트 내에서 데이터의 순위를 생성하지만 이전 순위 이후의 다음 순위는 해당 특정 행의 row_number입니다. 반면 Dense_Rank () SQL 함수는 row_number를 생성하는 대신 다음 숫자를 생성합니다. 아래는 개념을 명확히하는 SQL 예제입니다.

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

다음과 같은 출력을 생성합니다.

----------------------------
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 () : 연속적인 정수를 제공하지 않습니다.

Dense_rank () : 연속적인 정수를 제공합니다.

여기에 이미지 설명을 입력하십시오

위 그림에서 10008 zip의 순위는 dense_rank () 함수에 의해 2이고 row_number를 고려할 때 rank () 함수에 의해 24입니다.


0

Rank(), Dense_rank(), row_number() 이것들은 모두 창 기능입니다. 즉, 처음에 정렬 된 입력 세트에서 창으로 작동합니다. 이러한 창에는 요구 사항에 따라 다른 기능이 연결되어 있습니다. 위의 3 :

row_number()

이것으로 시작하여 row_number()관련 창 기능의 기초를 형성합니다. row_number()이름에서 알 수 있듯이 적용 된 행 세트에 고유 번호를 제공합니다. 각 행에 일련 번호를 제공하는 것과 유사합니다.

Rank()

의 Subversion은로 row_number()말할 수 있습니다 rank(). Rank ()는 중복 된 순서화 된 세트 행에 동일한 일련 번호를 부여하는 데 사용되지만 row_number()아래에서와 같이 rank () 의미가 중복 된 이후의 모든 행의 수와 유사하게 유지됩니다 . 데이터 2의 row_number () = rank ()는 둘 다 복제 형식이 다르다는 것을 의미합니다.

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

드디어,

Dense_rank ()는 위의 예제에서 알 수 있듯이 모든 데이터 1에 대해 rank () = dense_rank ()이지만 데이터 2에 대해서는 형식이 다르기 때문에 이름이 밀도를 암시하는 것처럼 rank ()의 ​​확장 버전입니다. 실제 데이터가 아닌 이전 순위 ()의 rank () 순서를 유지합니다.


0

RANK ()와 DENSE_RANK () 함수의 유일한 차이점은 "tie"가있는 경우입니다. 즉, 집합의 여러 값이 동일한 순위를 갖는 경우입니다. 이러한 경우 RANK ()는 비 연속적인 "순위"를 세트의 값에 지정하고 (타이가있을 때 정수 순위 값 사이의 간격이 발생 함) DENSE_RANK ()는 설정 (따라서 동점 인 경우 정수 순위 값 사이에 간격이 없음).

예를 들어 {30, 30, 50, 75, 75, 100} 세트를 고려하십시오. 이러한 세트의 경우 RANK ()는 {1, 1, 3, 4, 4, 6}을 리턴하고 (값 2와 5는 생략 됨) DENSE_RANK ()는 {1,1,2,3을 리턴합니다. 3,4}.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.