참고 도서: 2022 유선배 SQL개발자 과외노트
참고 자료: Wikipedia, oracle.com, oracletutorial.com
** SQLD 자격 시험을 준비하는 분들께 도움이 되고자 정리한 내용을 올리고 있습니다.
** 암기가 필요한 부분은 계속 보면서 외워주세요.
** 실습 환경 구성이 어려운 분들은 아래 링크를 이용하세요.
Oracle Live SQL 👈 클릭
** 오류가 있다면 댓글 주세요!
4.1 서브쿼리(Subquery)
-
하나의 쿼리 안에 존재하는 또 다른 쿼리이다.
SELECT 절 스칼라 서브쿼리(Scalar Subquery) FROM 절 인라인 뷰(Inline View) WHERE, HAVING 절 중첩 서브쿼리(Nested Subquery)
4.1.1 스칼라 서브쿼리(Scalar Subquery)
-
컬럼이 올 수 있는 대부분 위치에 사용이 가능하다. 컬럼 대신 사용되므로 반드시 하나의 값을 출력해야 한다.
-- scott schema SELECT ENAME ,(SELECT DNAME FROM DEPT B WHERE A.DEPTNO = B.DEPTNO) FROM EMP;
4.1.2 인라인 뷰(Inline View)
-
FROM 절 등 테이블명이 올 수 있는 위치에 사용한다.
-- scott schema SELECT * FROM ( SELECT EMPNO ,ENAME FROM EMP );
4.1.3 중첩 서브쿼리(Nested Subquery)
- WHERE 절과 HAVING 절에 사용한다.
- 비연관 서브쿼리: 메인 쿼리와 관계를 맺고 있지 않음
-- scott schema -- 비연관 서브쿼리 SELECT EMPNO ,ENAME FROM EMP WHERE DEPTNO = ( SELECT DEPTNO FROM DEPT WHERE DNAME = 'SALES' )
- 연관 서브쿼리: 메인 쿼리와 관계를 맺고 있음
-- scott schema -- 연관 서브쿼리 SELECT EMPNO ,ENAME FROM EMP A WHERE ENAME = ( SELECT ENAME FROM BONUS B WHERE A.ENAME = B.ENAME );
-
출력 값에 따라 단일 행, 다중 행, 다중 컬럼 서브쿼리로 나눌 수 있다.
단일 행 서브쿼리 서브쿼리가 1건 이하의 데이터를 출력한다. 단일 행 비교 연산자와 함께 사용할 수 있다. e.g. =, <, > , … 다중 행 서브쿼리 서브쿼리가 여러 건의 데이터를 출력한다. 다중 행 비교 연산자와 함께 사용할 수 있다. e.g. IN, ALL, ANY, … 다중 컬럼 서브쿼리 서브쿼리가 여러 컬럼의 데이터를 출력한다.
4.2 뷰(VIEW)
4.2.1 뷰(VIEW)란?
-
특정 SELECT 문 결과에 이름을 붙여 재사용이 가능한 오브젝트이다.
-
뷰는 가상 테이블로 조회만 가능하다.
4.2.2 뷰 생성 및 삭제
-- scott schema
-- CREATE VIEW
CREATE OR REPLACE VIEW V_DEPT AS
SELECT A.DEPTNO
,DNAME
,COUNT(A.DEPTNO) AS COUNT
FROM EMP A
INNER JOIN DEPT B
ON A.DEPTNO = B.DEPTNO
GROUP BY DEPTNO, DNAME;
-- USING VIEW
SELECT * FROM V_DEPT;
-- Output
-- 10|ACCOUNTING|3
-- 20|RESEARCH |5
-- 30|SALES |6
DROP VIEW V_DEPT;
4.3 집합 연산자
4.3.1 집합 연산자란?
- 집합 연산자는 두 개 이상 쿼리의 결과에 대한 집합을 가지고 연산하는 명령어이다.
4.3.2 UNION / UNION ALL
- UNION, UNION ALL은 합집합 개념이다. 둘은 매우 유사하나 차이점은, UNION ALL은 중복된 항목도 모두 조회한다는 점이다.
ID (A) | NAME (A) | ID (B) | NAME (B) | |
---|---|---|---|---|
1 | A | 1 | B | |
2 | C | 2 | C | |
3 | A | 3 | C | |
4 | B | 4 | B | |
5 | F |
-- UNION ALL
SELECT * FROM TABLE_A
UNION ALL
SELECT * FROM TABLE_B;
-- Output
-- 1|A
-- 2|C
-- 3|A
-- 4|B
-- 5|F
-- 1|B
-- 2|C
-- 3|C
-- 4|B
-- UNION
SELECT * FROM TABLE_A
UNION
SELECT * FROM TABLE_B;
-- Output
-- 1|A
-- 2|C
-- 3|A
-- 4|B
-- 5|F
-- 1|B
-- 3|C
4.3.3 INTERSECT
- INTERSECT는 교집합 개념이다. 공통된 부분만 중복을 제거하여 조회한다.
SELECT * FROM TABLE_A
INTERSECT
SELECT * FROM TALBE_B
-- Output
-- 2|C
-- 4|B
4.3.4 MINUS / EXCEPT
- MINUS / EXCEPT는 차집합 개념이다. 먼저 위치한 SELECT문을 기준으로 다른 SELECT 문과 공통된 레코드를 제외한 항목만 조회한다.
SELECT * FROM TABLE_A
EXCEPT
SELECT * FROM TALBE_B
-- Output
-- 1|A
-- 3|A
-- 5|F
4.4 그룹 함수
4.4.1 그룹 함수란?
-
하나의 행을 그룹으로 묶어 연산하여 하나의 결과로 리턴한다.
집계 함수 COUNT, SUM, AVG, MAX, MIN 등 소계 함수 ROLLUP, CUBE, GROUPING SETS 등
4.4.2 ROLLUP
- 소그룹 간의 소계 및 총계를 계산하는 함수이다.
-- scott schema
SELECT JOB
,DEPTNO
,COUNT(*) AS CNT
FROM EMP
GROUP BY ROLLUP(JOB, DEPTNO);
-- Output
-- CLERK |10 |1
-- CLERK |20 |2
-- CLERK |30 |1
-- CLERK |NULL|4
-- ANALYST |20 |2
-- ANALYST |NULL|2
-- MANAGER |10 |1
-- MANAGER |20 |1
-- MANAGER |30 |1
-- MANAGER |NULL|3
-- SALESMAN |30 |4
-- SALESMAN |NULL|4
-- PRESIDENT|10 |1
-- PRESIDENT|NULL|1
-- NULL |NULL|14
4.4.3 CUBE
- 소그룹 간의 소계 및 총계를 다차원적으로 계산하는 함수이다.
-- scott schema
SELECT JOB
,DEPTNO
,COUNT(*) AS CNT
FROM EMP
GROUP BY CUBE(JOB, DEPTNO);
-- Output
-- NULL |NULL|14
-- NULL |10 |3
-- NULL |20 |5
-- NULL |30 |6
-- CLERK |NULL|4
-- CLERK |10 |1
-- CLERK |20 |2
-- CLERK |30 |1
-- ANALYST |NULL|2
-- ANALYST |20 |2
-- MANAGER |NULL|3
-- MANAGER |10 |1
-- MANAGER |20 |1
-- MANAGER |30 |1
-- SALESMAN |NULL|4
-- SALESMAN |30 |4
-- PRESIDENT|NULL|1
-- PRESIDENT|10 |1
4.4.4 GROUPING SETS
- 특정 항목에 대한 소계를 구하는 함수이다. 인자값으로 ROLLUP이나 CUBE를 사용할 수 있다.
-- scott schema
SELECT JOB
,DEPTNO
,COUNT(*) AS CNT
FROM EMP
GROUP BY GROUPING SETS(JOB, DEPTNO, ());
-- Output
-- NULL |10 |3
-- NULL |20 |5
-- NULL |30 |6
-- NULL |NULL|14
-- PRESIDENT|NULL|1
-- MANAGER |NULL|3
-- ANALYST |NULL|2
-- SALESMAN |NULL|4
-- CLERK |NULL|4
4.4.5 GROUPING
- ROLLUP, CUBE, GROUPING SETS 등과 함께 쓰인다. 소계를 나타내는 행의 NULL 값을 처리할 수 있다.
-- scott schema
SELECT CASE GROUPING(JOB) WHEN 1 THEN 'TOTAL' ELSE JOB END
,DEPTNO
,COUNT(*) AS CNT
FROM SCOTT.EMP
GROUP BY ROLLUP(JOB, DEPTNO);
-- Output
-- CLERK |10 |1
-- ...
-- SALESMAN |NULL|4
-- PRESIDENT|10 |1
-- PRESIDENT|NULL|1
-- TOTAL |NULL|14
4.5 윈도우 함수
4.5.1 윈도우 함수란?
Row 간의 관계를 쉽게 정의하기 위한 함수이다. OVER 키워드와 함께 사용한다.
순위 함수 | RANK, DENSE_RANK, ROW_NUMBER |
---|---|
집계 함수 | SUM, MAX, MIN, AVG, COUNT |
행 순서 함수 | FRST_VALUE, LAST_VALUE, LAG, LEAD |
비율 함수 | CUME_DIST, PERCENT_RANK, NTILE, RATIO_TO_REPORT |
4.5.2 순위 함수
- RANK : 순위를 매긴다. 같은 순위가 존재할 경우 존재하는 수만큼 다음 순위를 건너뛴다.
-- scott schema
SELECT JOB
,COUNT(*) AS CNT
,RANK() OVER(ORDER BY COUNT(*) DESC) AS RANK
FROM SCOTT.EMP
GROUP BY JOB;
-- Output
-- SALESMAN |4|1
-- CLERK |4|1
-- MANAGER |3|3
-- ANALYST |2|4
-- PRESIDENT|1|5
-- 직급별 급여 순위
SELECT ENAME
,JOB
,SAL
,RANK() OVER(PARTITION BY JOB ORDER BY SAL DESC) AS RANK
FROM SCOTT.EMP;
-- Output
-- FORD |ANALYST |3000|1
-- SCOTT |ANALYST |3000|1
-- MILLER|CLERK |1300|1
-- ADAMS |CLERK |1100|2
-- JAMES |CLERK |950|3
-- SMITH |CLERK |800|4
-- JONES |MANAGER |2975|1
-- BLAKE |MANAGER |2850|2
-- CLARK |MANAGER |2450|3
-- KING |PRESIDENT|5000|1
-- ALLEN |SALESMAN |1600|1
-- TURNER|SALESMAN |1500|2
-- WARD |SALESMAN |1250|3
-- MARTIN|SALESMAN |1250|3
- DENSE_RANK: 순위를 매긴다. 같은 순위가 존재하더라도 다음 순위를 건너뛰지 않는다.
-- scott schema
SELECT JOB
,COUNT(*) AS CNT
,DENSE_RANK() OVER(ORDER BY COUNT(*) DESC) AS RANK
FROM SCOTT.EMP
GROUP BY JOB;
-- Output
-- SALESMAN |4|1
-- CLERK |4|1
-- MANAGER |3|2
-- ANALYST |2|3
-- PRESIDENT|1|4
- ROW_NUMBER: 순위를 매긴다. 동일한 순위라도 각기 다른 순위를 부여한다.
-- scott schema
SELECT JOB
,COUNT(*) AS CNT
,ROW_NUMBER() OVER(ORDER BY COUNT(*) DESC) AS RANK
FROM SCOTT.EMP
GROUP BY JOB;
-- Output
-- SALESMAN |4|1
-- CLERK |4|2
-- MANAGER |3|3
-- ANALYST |2|4
-- PRESIDENT|1|5
4.5.3 집계 함수
- SUM: 데이터의 합계를 리턴한다. 인수(Argument)로는 숫자형 데이터 타입(NUMBER, FLOAT, …)만 가능하다.
SELECT * FROM STUDENTS;
-- Output
-- 1|A|JAVA|10
-- 2|A|NODE|45
-- 3|B|JAVA|12
-- 4|B|NODE|51
-- 5|C|JAVA|8
-- 6|C|NODE|30
SELECT SUM(NUM) FROM (
SELECT 1 AS NUM FROM DUAL
UNION ALL
SELECT 2 AS NUM FROM DUAL
);
SELECT STUDENT_NAME
,SUBJECT
,SCORE
,SUM(SCORE) OVER(PARTITION BY STUDENT_NAME) AS TOTAL_SCORE
FROM STUDENTS;
-- Output
-- A|JAVA|10|55
-- A|NODE|45|55
-- B|JAVA|12|63
-- B|NODE|51|63
-- C|JAVA|8 |38
-- C|NODE|30|38
SELECT STUDENT_ID
,STUDENT_NAME
,SUBJECT
,SCORE
,SUM(SCORE) OVER(PARTITION BY STUDENT_NAME ORDER BY SCORE) AS SUM1
,SUM(SCORE) OVER(PARTITION BY STUDENT_NAME ORDER BY SCORE RANGE UNBOUNDED PRECEDING) AS SUM2
FROM STUDENTS;
-- Output
-- 1|A|JAVA|10|10|10
-- 2|A|NODE|45|55|55
-- 3|B|JAVA|12|12|12
-- 4|B|NODE|51|63|63
-- 5|C|JAVA|8 |8 |8
-- 6|C|NODE|30|38|38
- MAX: 데이터의 최대값을 리턴한다.
-- 과목별 최대값 조회
SELECT STUDENT_NAME
,SUBJECT
,SCORE
FROM (
SELECT STUDENT_NAME
,SUBJECT
,SCORE
,MAX(SCORE) OVER(PARTITION BY SUBJECT) MAX_SCORE
FROM STUDENTS
)
WHERE SCORE = MAX_SCORE;
-- Output
-- B|JAVA|12
-- B|NODE|51
- MIN: 데이터의 최솟값을 리턴한다.
-- 과목별 최솟값 조회
SELECT STUDENT_NAME
,SUBJECT
,SCORE
FROM (
SELECT STUDENT_NAME
,SUBJECT
,SCORE
,MIN(SCORE) OVER(PARTITION BY SUBJECT) MIN_SCORE
FROM STUDENTS
)
WHERE SCORE = MIN_SCORE;
-- Output
-- C|JAVA|8
-- C|NODE|30
- AVG: 데이터의 평균값을 리턴한다.
-- 과목별 평균값 이상
SELECT STUDENT_NAME
,SUBJECT
,SCORE
FROM (
SELECT STUDENT_NAME
,SUBJECT
,SCORE
,AVG(SCORE) OVER(PARTITION BY SUBJECT) AVG_SCORE
FROM STUDENTS
)
WHERE SCORE >= AVG_SCORE;
- COUNT: 데이터의 건수를 리턴한다.
SELECT COUNT(*)
FROM STUDENTS
WHERE SUBJECT = 'JAVA';
⁉️ 윈도우 함수 사용 옵션 |
---|
BETWEEN UNBOUNDED PRECEDING AND n PRECEDING |
BETWEEN UNBOUNDED AND CURRENT ROW |
BETWEEN UNBOUNDED PRECEDING AND n FOLLWING |
BETWEEN n PRECEDING AND n PRECEDING |
BETWEEN n PRECEDING AND CURRENT ROW |
BETWEEN n PRECEDING AND n FOLLOWING |
BETWEEN n PRECEDING AND UNBOUNDED FOLLOWING |
BETWEEN CURRENT ROW AND n FOLLOWING |
BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING |
BETWEEN n FOLLOWING ROW AND n FOLLOWING |
BETWEEN n FOLLOWING ROW AND UNBOUNDED FOLLOWING |
UNBOUNDED PRECEDING (default: RANGE UNBOUNDED PRECEDING) |
n PRECEDING |
CURRENT ROW |
4.5.4 행 순서 함수
- FIRST_VALUE: 파티션 별 선두에 위치한 데이터를 구한다.
-- scott schema
SELECT ENAME
,JOB
,SAL
,FIRST_VALUE(SAL) OVER(PARTITION BY JOB ORDER BY SAL DESC)
FROM SCOTT.EMP
WHERE JOB IN ('MANAGER', 'SALESMAN');
-- Output
-- JONES |MANAGER |2975|2975
-- BLAKE |MANAGER |2850|2975
-- CLARK |MANAGER |2450|2975
-- ALLEN |SALESMAN|1600|1600
-- TURNER|SALESMAN|1500|1600
-- WARD |SALESMAN|1250|1600
-- MARTIN|SALESMAN|1250|1600
- LAST_VALUE: 파티션 별 마지막에 위치한 데이터를 구한다.
-- scott schema
SELECT ENAME
,JOB
,SAL
,LAST_VALUE(SAL) OVER(
PARTITION BY JOB
ORDER BY SAL
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
FROM SCOTT.EMP
WHERE JOB IN ('MANAGER', 'SALESMAN');
-- Output
-- CLARK |MANAGER |2450|2975
-- BLAKE |MANAGER |2850|2975
-- JONES |MANAGER |2975|2975
-- WARD |SALESMAN|1250|1600
-- MARTIN|SALESMAN|1250|1600
-- TURNER|SALESMAN|1500|1600
-- ALLEN |SALESMAN|1600|1600
- LAG: 파티션 별 특정 수만큼 앞선 데이터를 구한다.
-- scott schema
SELECT ENAME
,JOB
,SAL
,LAG(SAL, 3) OVER(ORDER BY SAL) AS LAG
FROM SCOTT.EMP
WHERE JOB IN ('MANAGER', 'SALESMAN');
-- Output
-- MARTIN|SALESMAN|1250| -
-- WARD |SALESMAN|1250| -
-- TURNER|SALESMAN|1500| -
-- ALLEN |SALESMAN|1600|1250
-- CLARK |MANAGER |2450|1250
-- BLAKE |MANAGER |2850|1500
-- JONES |MANAGER |2975|1600
- LEAD: 파티션 별 특정 수만큼 뒤에 있는 데이터를 구한다.
-- scott schema
SELECT ENAME
,JOB
,SAL
,LEAD(SAL, 2) OVER(PARTITION BY JOB ORDER BY SAL) AS LAG
FROM SCOTT.EMP
WHERE JOB IN ('MANAGER', 'SALESMAN');
-- Output
-- CLARK |MANAGER |2450|2975
-- BLAKE |MANAGER |2850| -
-- JONES |MANAGER |2975| -
-- WARD |SALESMAN|1250|1500
-- MARTIN|SALESMAN|1250|1600
-- TURNER|SALESMAN|1500| -
-- ALLEN |SALESMAN|1600| -
4.5.5 비율 함수
- RATIO_TO_REPORT: 파티션 별 합계에서 비율을 구한다.
-- scott schema
SELECT ENAME
,JOB
,SAL
,SUM(SAL) OVER() AS SUM
,ROUND(SAL / SUM(SAL) OVER(), 3) AS "SAL/SUM"
,ROUND(RATIO_TO_REPORT(SAL) OVER(), 3) AS RATIO_TO_REPORT
FROM SCOTT.EMP
WHERE JOB = 'SALESMAN';
-- Output
-- ALLEN |SALESMAN|1600|5600|.286|.286
-- WARD |SALESMAN|1250|5600|.223|.223
-- MARTIN|SALESMAN|1250|5600|.223|.223
-- TURNER|SALESMAN|1500|5600|.268|.268
- PERCENT_RANK: 파티션의 첫 행을 0, 마지막 행을 1로 놓고 현재 행의 위치를 백분위 순위 값으로 구한다.
SELECT ROUND(PERCENT_RANK() OVER(ORDER BY NUM), 3) FROM (
SELECT 1 AS NUM FROM DUAL
UNION ALL
SELECT 2 FROM DUAL
UNION ALL
SELECT 3 FROM DUAL
UNION ALL
SELECT 4 FROM DUAL
);
-- Output
-- 0
-- .333
-- .667
-- 1
- CUME_DIST: 파티션에서 누적 백분율을 구한다.
SELECT ROUND(CUME_DIST() OVER(ORDER BY NUM), 3) FROM (
SELECT 1 AS NUM FROM DUAL
UNION ALL
SELECT 2 FROM DUAL
UNION ALL
SELECT 3 FROM DUAL
UNION ALL
SELECT 4 FROM DUAL
);
-- Output
-- .25
-- .5
-- .75
-- 1
- NTILE: 주어진 수만큼 행들을 n등분하여 등급을 구한다. 할당할 행이 남았을 경우 맨 앞 그룹부터 채운다.
-- scott schema
SELECT ENAME
,JOB
,SAL
,NTILE(4) OVER(ORDER BY SAL) AS "NTILE_4"
,NTILE(5) OVER(ORDER BY SAL) AS "NTILE_5"
FROM SCOTT.EMP;
-- Output
-- SMITH |CLERK |800 |1|1
-- JAMES |CLERK |950 |1|1
-- ADAMS |CLERK |1100|1|1
-- MARTIN|SALESMAN |1250|1|2
-- WARD |SALESMAN |1250|2|2
-- MILLER|CLERK |1300|2|2
-- TURNER|SALESMAN |1500|2|3
-- ALLEN |SALESMAN |1600|2|3
-- CLARK |MANAGER |2450|3|3
-- BLAKE |MANAGER |2850|3|4
-- JONES |MANAGER |2975|3|4
-- FORD |ANALYST |3000|4|4
-- SCOTT |ANALYST |3000|4|5
-- KING |PRESIDENT|5000|4|5
4.5.6 Top-N 쿼리
상위 n개의 데이터를 추출하기 위한 쿼리를 말한다.
- ROWNUM: 실제로 존재하지 않는 가짜 컬럼(Pseudo)을 생성한다.
-- scott schema
SELECT ROWNUM
,ENAME
,JOB
,SAL
FROM (
SELECT ENAME
,JOB
,SAL
FROM SCOTT.EMP
WHERE JOB IN ('PRESIDENT', 'ANALYST', 'MANAGER')
ORDER BY SAL DESC
);
-- Output
-- 1|KING |PRESIDENT|5000
-- 2|FORD |ANALYST |3000
-- 3|SCOTT|ANALYST |3000
-- 4|JONES|MANAGER |2975
-- 5|BLAKE|MANAGER |2850
-- 6|CLARK|MANAGER |2450
SELECT ROWNUM
,ENAME
,JOB
,SAL
FROM (
SELECT ENAME
,JOB
,SAL
FROM SCOTT.EMP
WHERE JOB IN ('PRESIDENT', 'ANALYST', 'MANAGER')
ORDER BY SAL DESC
)
~~WHERE ROWNUM = 5~~; --> WHERE ROWNUM <= 5
-- Output
-- no data found
- 윈도우 함수와 순위 함수
-- scott schema
-- ROW_NUMBER()
SELECT *
FROM (
SELECT ROW_NUMBER() OVER(ORDER BY SAL DESC) AS ROW_NUM
,ENAME
,JOB
,SAL
FROM SCOTT.EMP
)
WHERE ROW_NUM <= 5;
-- RANK()
SELECT *
FROM (
SELECT RANK() OVER(ORDER BY SAL DESC) AS RANK
,ENAME
,JOB
,SAL
FROM SCOTT.EMP
)
WHERE RANK <= 5;
-- DENSE_RANK()
SELECT *
FROM (
SELECT DENSE_RANK() OVER(ORDER BY SAL DESC) AS D_RANK
,ENAME
,JOB
,SAL
FROM SCOTT.EMP
)
WHERE D_RANK <= 5;
- ROW LIMITING
- OFFSET offset: 건너뛸 행의 개수를 지정한다.
- FETCH: 반환할 행의 개수나 백분율을 지정한다.
- ONLY: 지정된 행의 개수나 백분율만큼 행을 반환한다.
- WITH TIES: 마지막 행에 대한 동순위를 포함해서 반환한다.
-- [OFFSET offset {ROW | ROWS}]
-- [FETCH {FIRST | NEXT} [{rowcount | percent PERCENT}] {ROW | ROWS} {ONLY | WITH TIES}]
-- 5개의 행이 반환
SELECT empno
, sal
FROM emp
ORDER BY sal, empno
FETCH FIRST 5 ROWS ONLY;
-- OFFSET 만큼 건너뛴 행 이후의 전체 행이 반환
SELECT empno
, sal
FROM emp
ORDER BY sal, empno
OFFSET 5 ROWS;
4.5.7 셀프 조인(Self Join)
셀프 조인은 자신과 조인하는 것을 말한다. 같은 테이블이 두 번 이상 등장하므로 Alias를 열 표기를 명확(ORA-00918: column ambiguously defined
)하게 해야 한다.
-- scott schema
SELECT A.EMPNO AS MGR_NO
,ENAME AS MGR_NM
,B.EMPNO
,B.ENAME
FROM SCOTT.EMP A
INNER JOIN SCOTT.EMP B
ON A.EMPNO = B.MGR;
-- 나(A)의 사원번호가 관리자 번호(B)인 인스턴스를 연결(=)하겠다.
-- 내가 관리자인 녀셕들 내 밑으로 집합!
-- 7566|JONES|7902|FORD
-- 7566|JONES|7788|SCOTT
-- 7698|BLAKE|7499|ALLEN
-- 7698|BLAKE|7900|JAMES
-- 7698|BLAKE|7844|TURNER
-- 7698|BLAKE|7654|MARTIN
-- 7698|BLAKE|7521|WARD
-- 7782|CLARK|7934|MILLER
-- 7788|SCOTT|7876|ADAMS
-- 7839|KING |7698|BLAKE
-- 7839|KING |7782|CLARK
-- 7839|KING |7566|JONES
-- 7902|FORD |7369|SMITH
4.5.8 계층 쿼리
계층 구조를 이루는 컬럼을 출력할 때 사용한다.
-- 계층 쿼리에서 사용할 수 있는 키워드
-- CONNECT_BY_ROOT: 루트 노드의 컬럼 값을 반환
-- CONNECT_BY_ISLEAF: 가장 하위 노드인 경우 1을 반환 이외에는 0을 반환
-- ORDER SIBLINGS BY: 같은 레벨끼리 정렬하기 위해서 사용한다. (~~ORDER BY~~)
-- PRIOR: 이전 PATH와 현재 Row의 PARENT_PATH가 일치하는 Row를 연결하라
SELECT LEVEL
,PATH
,PARENT_PATH
,SYS_CONNECT_BY_PATH(PATH, '/') AS CONNECT_BY_PATH
,CONNECT_BY_ROOT PATH
,CONNECT_BY_ISLEAF
FROM (
SELECT 'Macintosh HD' AS PATH, NULL AS PARENT_PATH FROM DUAL
UNION ALL
SELECT 'USER' AS PATH, 'Macintosh HD' AS PARENT_PATH FROM DUAL
UNION ALL
SELECT 'Shared' AS PATH, 'USER' AS PARENT_PATH FROM DUAL
)
START WITH PARENT_PATH IS NULL
CONNECT BY PRIOR PATH = PARENT_PATH;
-- Output
-- 1|Macintosh HD| |/Macintosh HD |Macintosh HD|0
-- 2|USER |Macintosh HD|/Macintosh HD/USER |Macintosh HD|0
-- 3|Shared |USER |/Macintosh HD/USER/Shared|Macintosh HD|1
4.5.9 PIVOT 절과 UNPIVOT 절
행과 열을 전환하기 위해 사용한다.
- PIVOT
SELECT * FROM (SELECT job, deptno, sal FROM emp)
PIVOT (SUM(sal) FOR deptno IN (10, 20, 30))
ORDER BY 1;
- UNPIVOT
-- UNPIVOT [{INCLUDE | EXCLUDE} NULLS]
-- ( {column | (column [, col]...)}
-- FOR {column | (column [, col]...)}
-- IN ({column | (column [, col]...)} [AS {literal | (literal [, literal]...)}]
-- [, {column | (column [, col]...)} [AS {literal | (literal [, literal]...)}]]...
-- )
-- )