SQLD/SQL 기본과 활용
Oracle SQL) 계층형 쿼리와 셀프조인
DevPing9_
2020. 9. 1. 16:54
# 계층형 데이터
- 동일 테이블에 계층적으로 상위 및 하위 데이터가 포함된 데이터
ex) EMP 테이블의 사원번호 및 그 사원의 관리자번호
# 셀프조인
- FROM 절에 동일 테이블을 2번이상 기술하는 조인 (재귀호출)
# 순방향 전개
- 자식 노드로 전개
# 역방향 전개
- 부모 노드로 전개
# 리프데이터
- 자식노드가 존재하지 않는 데이터
# 루트데이터
- 계층형데이터에서 최상위에 위치하는 데이터 (순방향이냐 역방향이냐에 따라 루트가 달라짐)
# 사이클
- 데이터 전개 중 이미 나타났던 동일한 데이터가 다시 나타날때, 이것을 사이클이 발생했다고 지칭하며, 런타임 오류를 발생시킨다.
# 계층형 쿼리(질의) (Hierarchical Query)
# Oracle
# Syntax
SELECT ... FROM ... WHERE ...
START WITH 조건 AND 조건 ...
CONNECT BY [NOCYCLE] 조건 AND 조건 ...
[ORDER SIBLINGS BY 칼럼1, 칼럼2, ...]
+) [NOCYCLE] 키워드는 사이클이 발생한 이후의 데이터를 전개하지않을때 사용한다
+) [ORDER SIBLINGS BY 칼럼1, 칼럼2, ...] 키워드는 형제노드의 정렬기준을 정할때 사용한다
+) WHERE절은 모든 전개가 실행된 뒤 실행된다.
# 계층형 쿼리에서 사용되는 가상칼럼
1. LEVEL - 루트데이터이면 1, 하위데이터이면 2, 리프데이터까지 1씩 증가한다.
2. CONNECT_BY_ISLEAF - 전개과정에서 해당데이터가 리프데이터이면 1, 아니면 0
3. CONNECT_BY_ISCYCLE - 사이클발생 지점에 1을 리턴하여 사이클 발생지점을 체크할 수 있다.
# 계층형 쿼리에서 사용되는 함수
1. SYS_CONNECT_BY_PATH(col, str) - 데이터전개 경로표시
2. CONNECT_BY_ROOT(col) - 현재 전개할 데이터의 루트데이터 표시
# 사용예시
SQL> SELECT LEVEL AS LV
,EMPNO
,MGR
,CONNECT_BY_ISLEAF AS ISLEAF
FROM EMP
START WITH MGR IS NULL #(MGR == NULL 인 곳이 스타팅포인트)
CONNECT BY MGR = PRIOR EMPNO; #(추출될 데이터의 MGR == 이전노드의 EMPNO)
# 실행결과
LV EMPNO MGR ISLEAF
_____________________________________________
1 001 0
2 002 001 0 (# 리프노드가 아니다. 흘러온 방향대로 002의 자식노드를 검색한다)
3 003 002 1 (# EMPNO 003은 자식노드가없다 -> 003의 부모노드인 002로 돌아가서 다시 검색한다)
4 004 002 1 (# EMPNO 004은 자식노드가없다 -> 004의 부모노드인 002로 돌아가서 다시 검색한다)
5 313 001 1 (# EMPNO 313은 자식노드가없다 -> 313의 부모노드인 001로 돌아가서 다시 검색한다)
001 -> 002 -> 003 -> 002 -> 004 -> 002 -> 00
(
# EMPNO 313 의 MGR 001이 나오게 된 배경
( EMPNO 004은 자식노드가없다 -> 004의 부모노드인 002로 돌아가서 다시 검색한다 )
의 세부과정
-> 004를 MGR로 가지는 데이터를 찾는다(=004의 자식노드를 찾는다)
-> 발견하지 못했다 (004는 리프노드이다)
-> 스택에서 004를 삭제한다
-> 스택에서 데이터를 꺼낸다 (002) -> 002을 MGR로 가지는 노드 더이상 없음 -> 002 삭제
-> 스택에서 데이터를 꺼낸다 (001) -> 001을 MGR로 가지는 노드를 찾는다 -> EMP 313
)
# EMPNO 313 의 MGR 001이 나오게 된 배경을 보여주는 예시 쿼리문
SQL> SELECT LEVEL AS LV
,EMPNO
,MGR
,CONNECT_BY_ISLEAF AS ISLEAF
,SYS_CONNECT_BY_PATH(EMPNO,'->') AS PATH
FROM EMP
START WITH MGR IS NULL
CONNECT BY MGR = PRIOR EMPNO;
# 실행결과
LV EMPNO MGR ISLEAF PATH
___________________________________________________________________________
1 001 0 ->001
2 002 001 0 ->001->002
3 003 002 1 ->001->002->003
4 004 002 1 ->001->002->004
5 313 001 0 ->001->313
728x90