-- EMP 테이블에서 수당(COMM) 내림차순으로 순위를 매기는데 1등이 몇 명이라도 다음 순위는 2등이 되도록 하라. (NULL값은 정렬시 가장 큰 값이 된다) SQL> SELECT EMPNO, ENAME, SAL, COMM, DENSE_RANK() OVER (ORDER BY COMM DESC) D_RANK EMPNO ENAME SAL COMM D_RANK --------------------------------------------- -- 위예문에서 ORDER BY 기본 설정에 따라 NULL값이 맨 앞으로 왔는데 COMM 내림차순으로 하고맨 뒤로 보낼려면 NULLS LAST 구문을 사용하면 된다. SQL> SELECT EMPNO, ENAME, SAL, COMM, DENSE_RANK() OVER (ORDER BY COMM DESC NULLS LAST) D_RANK EMPNO ENAME SAL COMM D_RANK --------------------------------------------- -- 모든 사원출력 하면서 자신이 속한 부서에서 수당을 가장많이 받는 사원의 이름을 같이출력 SELECT EMPNO, ENAME, DEPTNO, MAX(ENAME) KEEP(DENSE_RANK FIRST ORDER BY comm DESC) OVER(partition by deptno) SAL -- 부서별로 그룹핑해서 부서내에서 수당 가장많이 받는 사원명 출력, partiotion by를 사용하지 -- 않고 from절 다음에 group by를 사용하면 출력되는 결과 자체가 그룹핑 된다. MAX(ENAME) KEEP(DENSE_RANK FIRST ORDER BY comm DESC) SAL -- EMP 테이블에서 부서별로 급여의 최대값, 최대급여사원번호, 최소값, 최소급여사원번호를 출력 MAX(empno) KEEP(DENSE_RANK FIRST ORDER BY sal DESC) max_empno, MIN(empno) KEEP(DENSE_RANK FIRST ORDER BY sal Asc) as min_empno DEPTNO MAX_SAL MAX_EMPNO MIN_SAL MIN_EMPNO -------------------------------------------------------------------------- -- 부서별로 그룹핑 하여 출력하는데, 입사한지 가장 오래된 직원의 급여, 가장 최근에 입사한 직원의 급여를 출력 MIN(sal) KEEP (DENSE_RANK FIRST ORDER BY hiredate) "Worst", MAX(sal) KEEP (DENSE_RANK LAST ORDER BY hiredate) "Best" ORDER BY deptno, "Worst", "Best"; ---------- ---------- ---------- -- 모든 사원들을 대상으로 그 사원이 속한 부서의 급여 최소, 최대, 급여합, 급여순위를 출력 SELECT ename, deptno, sal, MIN(sal) OVER (PARTITION BY deptno) "Worst", MAX(sal) OVER (PARTITION BY deptno) "Best", SUM(sal) OVER (PARTITION BY deptno) "SUM(SAL)", AVG(sal) OVER (PARTITION BY deptno) "AVG(SAL)", RANK() OVER (PARTITION BY deptno ORDER BY SAL DESC) "RANK" ENAME DEPTNO SAL Worst Best SUM(SAL) AVG(SAL) RANK ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- KING 10 5000 1300 5000 8750 2916.66667 1 CLARK 10 2450 1300 5000 8750 2916.66667 2 MARTIN 30 1250 950 2850 9400 1566.66667 4 WARD 30 1250 950 2850 9400 1566.66667 4 JAMES 30 950 950 2850 9400 1566.66667 -- MYEMP1에서 직무(JOB)가 ‘CLERK’ 인 사원을 출력하면서 사번, 이름, 급여, 그 사원이 속한 부서의 급여 평균을 같이 출력하라.(급여 평균은 소수이하 첫째자리에서 절삭하세오) SELECT EMPNO, ENAME, SAL, TRUNC(AVG(SAL)) OVER (PARTITION BY DEPTNO) AVG_SAL ------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | ------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 100K| 3906K| | 26294 (2)| 00:05:16 | | 1 | WINDOW SORT | | 100K| 3906K| 5528K| 26294 (2)| 00:05:16 | |* 2 | TABLE ACCESS FULL| MYEMP1 | 100K| 3906K| | 25264 (2)| 00:05:04 | ------------------------------------------------------------------------------------- -- MYEMP1, MYDEPT1에서 ‘1’번 부서의 사원을 출력하면서 사번, 이름, 급여, 부서명, 사원이 속한 부서의 급여 평균을 같이 출력하라.(급여 평균은 소수이하 첫째자리에서 절삭하세오) SELECT E.EMPNO, E.ENAME, E.SAL, D.DNAME, TRUNC(AVG(E.SAL) OVER (PARTITION BY E.DEPTNO)) AVG_SAL WHERE E.DEPTNO = D.DEPTNO EMPNO ENAME SAL DNAME AVG_SAL ---------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 2510K| 100M| 52440 (1)| 00:10:30 | | 1 | WINDOW BUFFER | | 2510K| 100M| 52440 (1)| 00:10:30 | | 2 | NESTED LOOPS | | 2510K| 100M| 25232 (1)| 00:05:03 | |* 3 | TABLE ACCESS FULL| MYDEPT1 | 1 | 14 | 3 (0)| 00:00:01 | |* 4 | TABLE ACCESS FULL| MYEMP1 | 2510K| 67M| 25229 (1)| 00:05:03 | ------------------------------------------------------------------------------- -- MYEMP1 테이블에서 가장 오래전에 입사한 사원중 급여를 가장 많이 받는 사원을 출력하시오. (아래 예문에서 ROW_NUMBER()대신 RANK()를 사용해도 된다) SELECT EMPNO, ENAME, SAL, HIREDATE SELECT EMPNO, ENAME, SAL, HIREDATE, ROW_NUMBER() OVER (ORDER BY HIREDATE ASC, SAL DESC) RNUM ---------- -------------------- ---------- -------- 9999000 박길동9999000 3999000 15/05/01 ------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | ------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 10M| 953M| | 118K (1)| 00:23:44 | |* 1 | VIEW | | 10M| 953M| | 118K (1)| 00:23:44 | |* 2 | WINDOW SORT PUSHED RANK| | 10M| 333M| 459M| 118K (1)| 00:23:44 | | 3 | TABLE ACCESS FULL | MYEMP1 | 10M| 333M| | 25271 (2)| 00:05:04 | ------------------------------------------------------------------------------------------- -- 아래는 Range와 Row 차이에 관한 예문이다. -- Emp 테이블의 모든 사원을 출력하는데 해당 레코드의 입사일자를 기준으로 3개월전, 후의 데이터를 윈도우로 해서 분석하는 예문이다. Range는 OREDER BY 절에 DATE형이나 표현식이 올 때 사용가능하다. select empno, ename, hiredate, sal, avg(sal) over(order by hiredate range between interval'3' month preceding and interval '3' month following) sal_avg 7499 ALLEN 81/02/20 14639.54 6249.515 7521 WARD 81/02/22 1830.13 6249.515 7566 JONES 81/04/02 4355.7 5717.022 7698 BLAKE 81/05/01 4172.69 5717.022 7782 CLARK 81/06/09 3587.05 3577.8975 -- 아래는 입사일자 기준으로 90일 이전, 이후의 데이터를 분석을 위한 범위로 두었다. select empno, ename, hiredate, sal, range between 90 PRECEDING and 90 following) sal_avg 7499 ALLEN 81/02/20 14639.54 6249.515 7521 WARD 81/02/22 1830.13 6249.515 7566 JONES 81/04/02 4355.7 5717.022 7698 BLAKE 81/05/01 4172.69 5717.022 7782 CLARK 81/06/09 3587.05 4038.48 -- Rows를 사용하면 물리적인 행이 기준이 된다. 즉 앞뒤로 90개의 행이 윈도우가 된다. Emp 테이블은 전체 레코드가 14건이므로 모두 같은 같을 가지게 된다. select empno, ename, hiredate, sal, rows between 90 PRECEDING and 90 following) sal_avg 7499 ALLEN 81/02/20 14639.54 5025.5707 7521 WARD 81/02/22 1830.13 5025.5707 7566 JONES 81/04/02 4355.7 5025.5707 7698 BLAKE 81/05/01 4172.69 5025.5707 |