Oracle

오라클 『RANK() OVER()』

new민지(); 2023. 10. 24. 22:54

■ RANK() OVER()

RANK()  OVER() → 등수 (순위)를 반환하는 함수이다.

기본 예제를 살펴보자.

 

RANK() 예제 1) 

SELECT EMPNO 사원번호, ENAME 사원명, DEPTNO 부서번호, SAL 급여
     , RANK() OVER(ORDER BY SAL DESC) "전체 급여 순위"
FROM EMP;

위 코드에서 RANK() OVER(ORDER BY SAL SESC) 라는 구문은 SAL(급여)가 높은순서로 등수를 반환하겠다는 뜻이다.

결과 값은 다음과 같다.

 

RANK() 예제 1 결과)

	                       부서 전체
7839	KING	10	5000	1	1
7902	FORD	20	3000	1	2
7788	SCOTT	20	3000	1	2
7566	JONES	20	2975	3	4
7698	BLAKE	30	2850	1	5
7782	CLARK	10	2450	2	6
7499	ALLEN	30	1600	2	7
7844	TURNER	30	1500	3	8
7934	MILLER	10	1300	3	9
7521	WARD	30	1250	4	10
7654	MARTIN	30	1250	4	10
7876	ADAMS	20	1100	4	12
7900	JAMES	30	950 	6	13
7369	SMITH	20	800	5	14

PARTITION BY 함수를 사용해보자.

PARTITION BY 말 그대로 BY 다음으로 오는 컬럼으로 나누고 조건으로 등수를 반환하겠다는 것이다.

예제를 보면 간단하게 이해할 수 있다.

 

RANK() 예제 2)

SELECT EMPNO 사원번호, ENAME 사원명, DEPTNO 부서번호, SAL 급여
     , RANK() OVER(PARTITION BY DEPTNO ORDER BY SAL DESC) "부서별급여순위"
     , RANK() OVER(ORDER BY SAL DESC) "전체급여순위"
FROM EMP
ORDER BY DEPTNO;

RANK() OVER(PARTITION BY DEPTNO ORDER BY SAL DESC)라는 구문은

부서번호가 같은 사람들을 비교하여 급여가 높은 순서대로 등수를 반환한다는 뜻이다.

 

RANK() 예제 2 결과)

	     부서번호          부서   전체
7839	KING	10	5000	1	1
7782	CLARK	10	2450	2	6
7934	MILLER	10	1300	3	9
7902	FORD	20	3000	1	2
7788	SCOTT	20	3000	1	2
7566	JONES	20	2975	3	4
7876	ADAMS	20	1100	4	12
7369	SMITH	20	800	5	14
7698	BLAKE	30	2850	1	5
7499	ALLEN	30	1600	2	7
7844	TURNER	30	1500	3	8
7654	MARTIN	30	1250	4	10
7521	WARD	30	1250	4	10
7900	JAMES	30	950 	6	13

결과를 보면 부서번호가 같은 사람들의 급여를 비교하여 등수를 반환하는 것을 알 수 있다. 

등수와 관련된 함수중 또 다른 함수도 있다.

 

바로 DENSE_RANK() 이다. 

서열을 반환하는 함수로 1등이 2명이어도 3등이 아닌 2등으로 반환해주는 함수이다.

 

DENSE_RANK()  예제 1)

SELECT EMPNO 사원번호, ENAME 사원명, DEPTNO 부서번호, SAL 급여
     , DENSE_RANK() OVER(PARTITION BY DEPTNO ORDER BY SAL DESC) "부서별급여서열"
     , DENSE_RANK() OVER(ORDER BY SAL DESC) "전체급여서열"
FROM EMP
ORDER BY 3,4 DESC;

RANK() 함수와 작성하는 방법은 크게 다르지 않다. RANK() 함수 자리에 DENSE_RANK() 를 넣으면 된다.

바로 결과를 알아보자.

 

DENSE_RANK()  예제1 결과)

7839	KING	10	5000	1	1
7782	CLARK	10	2450	2	5
7934	MILLER	10	1300	3	8

7902	FORD	20	3000	1	2
7788	SCOTT	20	3000	1	2
7566	JONES	20	2975	2	3        -- 앞에 동일한 결과가 있어도 1 → 3 이 아니라 1 → 2가 온다.
7876	ADAMS	20	1100	3	10      
7369	SMITH	20	800	4	12


7698	BLAKE	30	2850	1	4
7499	ALLEN	30	1600	2	6
7844	TURNER	30	1500	3	7
7654	MARTIN	30	1250	4	9       
7521	WARD	30	1250	4	9
7900	JAMES	30	950	5	11	-- 앞에 동일한 결과가 있어도 4 → 6 이 아니라 4 → 5가 온다.

20번 부서의 FORD 와 SCOTT 이 공동 1등이지만 JONES의 등수는 3등이 아닌 2등이라는 것을 알 수 있다.

위의 RANK() 함수와는 다른 결과 값이다.

마찬가지로 30번 부서의 MARTIN 과 WARD가 공동 4등이지만 JAMES의 등수는 5등으로 나온다.

 

RANK() 함수를 사용하여 다양한 예제를 풀어보자.

EMP 테이블의 사원 데이터를 사원명, 부서번호, 연봉, 부서내 연봉 순위, 전체 연봉 순위 항목으로 조회해보자

 

RANK() 예제 3-1)

SELECT ENAME 사원명, DEPTNO 부서번호, SAL*12+NVL(COMM,0) "연봉"
     , RANK() OVER(PARTITION BY DEPTNO ORDER BY SAL*12+NVL(COMM,0) DESC) "부서내연봉순위" 
     , RANK() OVER(ORDER BY SAL*12+NVL(COMM,0) DESC) "전체연봉순위"
FROM EMP
ORDER BY DEPTNO;

RANK() 예제 3-2) 서브쿼리문 사용

SELECT T.* 
      ,RANK() OVER(PARTITION BY T.부서번호 ORDER BY T.연봉 DESC) "부서내연봉순위"
      ,RANK() OVER(ORDER BY T.연봉 DESC)"전체연봉순위"
FROM
(
    SELECT ENAME 사원명, DEPTNO 부서번호, SAL*12+NVL(COMM,0) "연봉"
    FROM EMP
) T
ORDER BY T.부서번호;

RANK() 예제 3 결과)

KING	10	60000	1	1
CLARK	10	29400	2	6
MILLER	10	15600	3	10
FORD	20	36000	1	2
SCOTT	20	36000	1	2
JONES	20	35700	3	4
ADAMS	20	13200	4	12
SMITH	20	9600	5	14
BLAKE	30	34200	1	5
ALLEN	30	19500	2	7
TURNER	30	18000	3	8
MARTIN	30	16400	4	9
WARD	30	15500	5	11
JAMES	30	11400	6	13

EMP 테이블에서 전체연봉순위가 1등부터 5등까지만 사원명, 부서번호, 연봉, 전체 연봉순위 항목으로 조회한다.

 

RANK() 예제 4) 서브쿼리문 사용

SELECT T.*
FROM
(
    SELECT ENAME 사원명, DEPTNO 부서번호 , SAL*12+NVL(COMM,0) 연봉
          ,RANK() OVER(ORDER BY SAL*12+NVL(COMM,0) DESC) "전체연봉순위"
    FROM EMP
) T
WHERE 전체연봉순위 < 6;

RANK() 예제 4 결과)

KING	10	60000	1
SCOTT	20	36000	2
FORD	20	36000	2
JONES	20	35700	4
BLAKE	30	34200	5