START WITH ~ CONNECT BY
계층 쿼리를 사용하는 예)
회사에서 개발팀, 기획팀이 있다고 하면
개발팀에는 개발 1팀, 개발 2팀 / 기획팀에는 기획 1팀, 기획 2팀과 같이 하위 팀들이 있다.
자식노드에 관한 정보를 나타내기 위해서는 계층적 쿼리를 사용하여 화면에 아래와 같이 보여줄 수 있다.
개발팀
|
|ㅡㅡㅡㅡ개발 1팀
| |
| |ㅡ 개발 1팀( 기능 )
|
|ㅡㅡㅡㅡ개발 2팀
계층적 쿼리의 형태를 보자.
START WITH condition CONNECT BY NOCYCLE condition
* START WITH condition - condition에는 root row(s) 가 명시되어야 한다. ex) 개발팀
* CONNECT BY - CONNECT BY뒤에는 root row(s)와 child row(s)의 관계를 명시해야한다. ex) 개발팀 > 개발 1팀
* PRIOR 연산자 ( 상위 행의 컬럼임을 보여줌 )
* 계층 조회는 condition에서 단 하나 뿐인 부모 행을 참조하기 위해 PRIOR 연산자로 한정할 필요가 있다.
... PRIOR expr = expr
or
... expr = PRIOR expr
위와 같은 예제에서 CONNECT BY PRIOR 개발팀 = 개발 1팀 이렇게 사용하면, 개발 1팀에서 개발팀 (아래 -> 위)으로 역행하는 트리가 구성된다. ( 개발 1팀의 부모를 찾자 )
반대로, CONNECT BY PRIOR 개발 1팀 = 개발팀 이렇게하면, 개발팀아래에 있는 부속팀들을 찾자.
* CONNECT BY 조건이 여러개인 경우는 PRIOR 연산자를 필요로하는 조건은 1개뿐이지만, PRIOR 조건을 여러 개 지정할 수도 있다.
CONNECT BY last_name != 'King' AND PRIOR employee_id = manager_id ...
CONNECT BY PRIOR employee_id = manager_id and
PRIOR account_mgr_id = customer_id ...
* 참고
* PRIOR는 단항 연산자이며 단항 + 및 - 산술 연산자와 우선 순위가 같다.
* [단항 연산자(참,거짓 / 부호변경 / 값증감)에 +,- 는 부호를 말하며 산술 연산자의 +,-는 사칙연산을 말한다.]
* PRIOR는 항등 연산자로 열 값을 비교할 때 가장 일반적으로 사용된다.
* [항등 연산자 : =, == 와 ===]
* CONNECT BY 절에 항등 연산자(=) 이외의 다른 연산자도 이론상으로는 가능하다.
* 하지만, 다른 연산자를 사용할 경우, Oracle은 무한반복을 초래 할 수 있으니 항등 연산자를 사용하길 권고한다.
Oracle의 계층 질의 처리 방법
* 결합이 존재하는 경우 결합이 FROM절에 지정되어 있는지 WHERE절로 지정되어 있는지에 관계없이 CONNECT BY절이 먼저 평가된다.
* CONNECT BY 조건이 평가된다 -> 나머지 WHERE절이 평가된다.
Oracle은 이러한 평가의 정보를 사용하여 다음과 같이 계층을 형성한다.
* Oracle은 계층 구조의 루트 행 (START WITH 뒤에 올 행)을 선택한다. 1단계
* Oracle은 각 루트 행의 자식 행을 선택한다. 2단계
* 자식 행은 하나의 루트 행에 대해 CONNECT BY 조건을 충족해야한다. 2단계
* Oracle은 연속 된 세대의 자식 행을 선택한다. 3단계
* Oracle은 먼저 2 단계에서 반환 된 행의 자식을 선택한 다음 그 자식의 자식을 선택한다. 3단계
* 쿼리에 결합되지 않은 WHERE 절이 포함되어있는 경우 Oracle은 WHERE 절 조건을 충족하지 않는 모든 행을 계층으로 부터 삭제한다. 4단계
* 단, Oracle이 조건을 충족하지 않는 행의 모든 자식을 제거하는 것이 아니라 각 행에 대해 개별적으로 조건에 대해 평가한다. 4단계
위의 계층 구조를 보자.
* 부모 행의 자식을 찾기 위해, Oracle은 부모 행에 대한 CONNECT BY 조건 PRIOR 식을 평가한다.
* 조건이 참인 행은 부모의 자식이다.
* CONNECT BY 조건 쿼리에서 다른 조건을 포함할 수 있다.
* CONNECT BY 조건에는 서브 쿼리를 사용할 수 없다.
* START WITH는 서브쿼리를 사용할 수 있다.
* 예외
* CONNECT BY 조건에 따라 계층 구조에서 루프가 발생한 경우 Oracle은 오류를 반환한다.
* 행이 다른 행의 부모 (조부모 또는 직계 조상)와 자식 (또는 손자 또는 직계 후손) 모두 인 경우 루프가 발생한다.
* 주의할 점
* 계층 쿼리에서는 ORDER BY 또는 GROUP BY를 모두 지정하면 안된다.
* CONNECT BY 결과의 계층 순서가 손상 때문
이제 예제를 보며 정리해 보자.
* 예제
1) 다음 계층 쿼리는 CONNECT BY 절을 사용하여 직원과 관리자 사이의 관계를 정의한 예제다.
SELECT employee_id, last_name, manager_id
FROM employees
CONNECT BY PRIOR employee_id = manager_id;
EMPLOYEE_ID LAST_NAME MANAGER_ID
----------- -------결 과 값--------- ----------
101 Kochhar 100
108 Greenberg 101
109 Faviet 108
110 Chen 108
111 Sciarra 108
112 Urman 108
113 Popp 108
200 Whalen 101
=> employee_id 와 manager_id가 동일레벨 일 경우를 보여준다.
상위 manager_id에서 하위 employee_id로 흐르는 트리
2) 다음 계층 쿼리는 계층 구조의 루트 행을 지정하기위한 START WITH 절과 계층정렬을 하기 위한 SIBLINGS 키워드를 사용하고 ORDER BY 절을 추가한 예제다.
SELECT last_name, employee_id, manager_id, LEVEL
FROM employees
START WITH employee_id = 100
CONNECT BY PRIOR employee_id = manager_id
ORDER SIBLINGS BY last_name;
LAST_NAME EMPLOYEE_ID MANAGER_ID LEVEL
------------------------- ----------- ---------- ----------
King 100 1
Cambrault 148 100 2
Bates 172 148 3
Bloom 169 148 3
Fox 170 148 3
Kumar 173 148 3
Ozer 168 148 3
Smith 171 148 3
De Haan 102 100 2
Hunold 103 102 3
Austin 105 103 4
=> START WITH에 employee_id 가 100인 루트노드 행을 지정하고 employee_id와 manager_id가 동일 레벨일 경우 last_name이 먼저인 것부터 정렬했다.
상위 manager_id에서 하위 employee_id로 흐르는 트리
참고 링크
[Oracle] 계층적 쿼리 SYS_CONNECT_BY_PATH
계층적 쿼리 SYS_CONNECT_BY_PATH 아래는 이 쿼리의 문법이다. SYS_CONNECT_BY_PATH(column, char) SYS_CONNECT_BY_PATH에 대한 설명을 봅시다. * SYS_CONNECT_BY_PATH는 계층적 쿼리에서만 유효하다. * CONNECT..
docu94.tistory.com
https://docs.oracle.com/cd/B19306_01/server.102/b14200/queries003.htm#i2053935
Hierarchical Queries
Hierarchical Queries If a table contains hierarchical data, then you can select rows in a hierarchical order using the hierarchical query clause: hierarchical_query_clause::= Description of the illustration hierarchical_query_clause.gif START WITH specifie
docs.oracle.com
도움이 되셨으면 공감과 광고 한번 씩 눌러주시면 감사합니다!!
[Oracle] ROW_NUMBER()가 뭐에요? (3) | 2019.04.17 |
---|---|
[Oracle] LEVEL 계층 구조 및 사용법 (0) | 2019.04.16 |
[Oracle] 계층적 쿼리 SYS_CONNECT_BY_PATH (0) | 2019.04.16 |
[Oracle] LAG, LEAD 이전글, 다음글 - 손쉽게 코딩하기 (0) | 2019.04.16 |
[ORACLE] function 생성, 사용방법 (0) | 2019.04.03 |
내 블로그 - 관리자 홈 전환 |
Q
Q
|
---|---|
새 글 쓰기 |
W
W
|
글 수정 (권한 있는 경우) |
E
E
|
---|---|
댓글 영역으로 이동 |
C
C
|
이 페이지의 URL 복사 |
S
S
|
---|---|
맨 위로 이동 |
T
T
|
티스토리 홈 이동 |
H
H
|
단축키 안내 |
Shift + /
⇧ + /
|
* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.