2과목 · SQL 기본 및 활용·14장
계층형 질의
Oracle의 CONNECT BY, 레벨 함수, 표준 재귀 CTE까지 계층형 조회를 정리합니다.
1. 계층형 데이터란
부모-자식 관계가 같은 테이블 안에 반복되는 구조. 사원-상사, 카테고리-하위 카테고리, 조직도, 폴더 트리.
예) emp(emp_id, name, manager_id) — manager_id는 같은 테이블의 emp_id를 참조.
2. Oracle CONNECT BY
SELECT LEVEL,
LPAD(' ', (LEVEL-1)*2) || name AS tree,
CONNECT_BY_ROOT name AS root,
SYS_CONNECT_BY_PATH(name, '/') AS path,
CONNECT_BY_ISLEAF AS is_leaf
FROM emp
START WITH manager_id IS NULL -- 루트 조건
CONNECT BY PRIOR emp_id = manager_id; -- 부모 → 자식 방향
키워드 정리
| 키워드 | 의미 |
|---|---|
START WITH |
루트 행 조건 |
CONNECT BY |
부모-자식 관계식 |
PRIOR |
이전(부모) 행의 값 |
LEVEL |
루트에서의 깊이 (1부터) |
CONNECT_BY_ROOT col |
루트 행의 값 |
SYS_CONNECT_BY_PATH(col, delim) |
루트부터의 경로 |
CONNECT_BY_ISLEAF |
리프면 1, 아니면 0 |
CONNECT_BY_ISCYCLE |
순환 감지 (NOCYCLE 옵션 필요) |
ORDER SIBLINGS BY
형제 노드 간 정렬을 유지하며 트리 구조를 보존.
SELECT LEVEL, name FROM emp
START WITH manager_id IS NULL
CONNECT BY PRIOR emp_id = manager_id
ORDER SIBLINGS BY name;
3. 방향의 차이: 부모→자식 vs 자식→부모
- 부모 → 자식 (하향):
CONNECT BY PRIOR emp_id = manager_id - 자식 → 부모 (상향):
CONNECT BY PRIOR manager_id = emp_id
PRIOR가 붙은 쪽이 이미 방문한(앞 행) 컬럼입니다.
4. 표준 SQL — 재귀 CTE (WITH RECURSIVE)
Oracle 외 대부분 DBMS (PostgreSQL, MySQL 8+, SQL Server)는 재귀 CTE를 씁니다.
WITH RECURSIVE tree AS (
-- 앵커: 루트 행
SELECT emp_id, name, manager_id, 1 AS lvl, CAST(name AS TEXT) AS path
FROM emp
WHERE manager_id IS NULL
UNION ALL
-- 재귀: 자식을 붙임
SELECT e.emp_id, e.name, e.manager_id, t.lvl + 1, t.path || '/' || e.name
FROM emp e
JOIN tree t ON e.manager_id = t.emp_id
)
SELECT * FROM tree ORDER BY path;
5. 출력 팁
들여쓰기로 시각적 트리 출력:
LPAD(' ', (LEVEL - 1) * 2) || name
순환(사이클) 방지:
CONNECT BY NOCYCLE PRIOR emp_id = manager_id;
6. CONNECT_BY_ISCYCLE의 오해
CONNECT_BY_ISCYCLE는 현재 행의 자식이 이미 방문된 조상인지 여부를 알려준다. 즉 "순환 노드"에서 1.- 단순히 "루트까지 경로"를 표시하는 것이 아님. 시험 선택지에서 "ROOT까지의 경로에 존재하는 데이터"로 설명하면 오답.
7. 자주 출제되는 포인트
- LEVEL은 1부터 시작.
CONNECT_BY_ISLEAF: LEAF면 1, 아니면 0. (0/1 방향 주의)SYS_CONNECT_BY_PATH: 루트부터의 경로.PRIOR위치로 방향을 결정.- 표준 SQL은 WITH RECURSIVE.
8. 요약 체크리스트
- CONNECT BY 키워드와 함수를 구분해 사용할 수 있다.
- 부모→자식 / 자식→부모 방향을 PRIOR로 제어할 수 있다.
- WITH RECURSIVE로 같은 결과를 낼 수 있다.
- ISLEAF / ISCYCLE의 의미를 정확히 안다.