결론 먼저
SQLD 계층형 질의 문제는 PRIOR가 어느 컬럼에 붙어 있는지 한 줄로 거의 다 결정돼요. 그리고 한 가지 더, START WITH → CONNECT BY → WHERE 평가 순서를 헷갈리면 결과 행 수가 통째로 틀립니다. 이 두 가지만 잡고 가면 1–2문제는 그냥 가져옵니다.
왜 시험에 매번 나오는가
SQLD 2과목(SQL 활용)에서 매회 1–2문제가 계층형 질의로 출제돼요. 합격 커트가 60점인 시험에서 1문제는 2점, 두 문제면 4점. 비전공자 입장에서 실무에서 한 번도 안 써본 문법이라 시험 직전에 외워야 하는 주제입니다.
문제는 이게 그냥 외워서 풀리는 게 아니라 트리를 머릿속에 그릴 줄 알아야 풀린다는 점이에요. 그래서 PRIOR 위치 헷갈림 → 결과 행 통째로 틀림 → 한 문제가 아니라 두 문제 날리는 패턴이 자주 나옵니다.
기본 문법
SELECT 컬럼들
FROM 테이블
[WHERE 조건]
START WITH 시작조건
CONNECT BY [PRIOR] 부모자식조건
[ORDER SIBLINGS BY 정렬컬럼];
각 절의 역할:
- START WITH — 트리의 뿌리(루트)를 어디로 잡을지
- CONNECT BY — 부모-자식 관계를 어떻게 이을지
- PRIOR — 어느 행이 "기준 행(이전 행)"인지 표시
- ORDER SIBLINGS BY — 같은 부모를 가진 형제들 사이의 정렬
예시 — 조직도 테이블로 손으로 그리기
EMP 테이블이 이렇게 있다고 해볼게요.
| emp_id | name | mgr_id |
|---|---|---|
| 1 | 사장 | NULL |
| 2 | 본부장A | 1 |
| 3 | 본부장B | 1 |
| 4 | 팀장A | 2 |
| 5 | 사원1 | 4 |
조직도를 그려보면:
사장(1)
├── 본부장A(2)
│ └── 팀장A(4)
│ └── 사원1(5)
└── 본부장B(3)
순방향 — 위에서 아래로 (사장 → 사원)
SELECT LEVEL, name
FROM EMP
START WITH mgr_id IS NULL
CONNECT BY PRIOR emp_id = mgr_id;
결과:
| LEVEL | name |
|---|---|
| 1 | 사장 |
| 2 | 본부장A |
| 3 | 팀장A |
| 4 | 사원1 |
| 2 | 본부장B |
PRIOR emp_id = mgr_id를 풀어 읽으면 "이전 행의 emp_id가 다음 행의 mgr_id와 같다" = 부모의 emp_id로 자식의 mgr_id를 찾는다 = 부모에서 자식 방향.
역방향 — 아래에서 위로 (사원 → 사장)
SELECT LEVEL, name
FROM EMP
START WITH emp_id = 5
CONNECT BY PRIOR mgr_id = emp_id;
결과:
| LEVEL | name |
|---|---|
| 1 | 사원1 |
| 2 | 팀장A |
| 3 | 본부장A |
| 4 | 사장 |
PRIOR mgr_id = emp_id = "이전 행의 mgr_id가 다음 행의 emp_id" = 자식의 상사(mgr_id)를 따라 부모로 올라간다.
PRIOR 위치 외우는 법
말로 하면 다음 시험에서 또 헷갈려요. 시험장 답안지 여백에 이렇게 그려두면 안 흔들립니다.
PRIOR가 붙은 컬럼 = "이전 행(기준 행)의 그 컬럼 값"
PRIOR emp_id = mgr_id→ 이전 행 emp_id ▶ 다음 행 mgr_id (위→아래, 순방향)PRIOR mgr_id = emp_id→ 이전 행 mgr_id ▶ 다음 행 emp_id (아래→위, 역방향)
화살표로 방향만 잡으면 어떤 변형이 나와도 풀려요. 이름 컬럼이 parent_id, boss_id로 바뀌어도 같은 원리.
의사컬럼(Pseudo Column) 4가지
계층형 질의에서만 쓸 수 있는 컬럼들이에요. 시험에 그대로 출제되니 이름과 결과 외워둬야 합니다.
| 의사컬럼 | 의미 | 예시 |
|---|---|---|
LEVEL | 트리 깊이 (루트가 1) | 1, 2, 3 ... |
CONNECT_BY_ROOT 컬럼 | 해당 행의 루트 컬럼 값 | 모든 행에 "사장" |
CONNECT_BY_ISLEAF | 리프 노드면 1, 아니면 0 | 사원1 → 1 |
SYS_CONNECT_BY_PATH(컬럼, '구분자') | 루트부터 경로 문자열 | /사장/본부장A/팀장A |
특히 SYS_CONNECT_BY_PATH는 출력 결과가 그대로 보기에 나와서, 구분자가 어디 들어가는지 정확히 외워둬야 해요. 첫 글자에도 구분자가 붙습니다(/사장이지 사장이 아니에요).
자주 틀리는 함정 5가지
1. WHERE가 CONNECT BY보다 먼저 평가된다고 착각
이게 가장 자주 틀리는 부분입니다. 평가 순서는:
START WITH → CONNECT BY → WHERE → SELECT → ORDER BY
즉 WHERE는 트리가 다 만들어진 다음에 가지치기만 합니다. 특정 노드를 WHERE로 빼도 그 자식들은 그대로 살아남아요.
-- 본부장A는 빠지지만 그 밑의 팀장A, 사원1은 결과에 남음
SELECT name
FROM EMP
WHERE name <> '본부장A'
START WITH mgr_id IS NULL
CONNECT BY PRIOR emp_id = mgr_id;
이거 시험에 진짜 자주 나옵니다. "본부장A를 제외하면 결과 행이 몇 개?"라고 물어보면 자식들 살아 있다는 걸 잊고 4개 찍어버려요.
2. CONNECT BY 절에 AND로 조건을 같이 쓰면 결과가 다름
-- 본부장A부터는 트리 전개가 끊김
CONNECT BY PRIOR emp_id = mgr_id AND name <> '본부장A'
CONNECT BY 안에 조건을 넣으면 그 노드부터 자식까지 통째로 잘립니다. WHERE랑 결과가 완전히 달라요. 이걸 비교하는 문제가 단골입니다.
3. START WITH 없으면 어떻게 되는가
START WITH를 빼면 모든 행이 각각 시작점이 됩니다. 그래서 결과 행이 폭증해요. 5명짜리 조직도면 5개 트리가 동시에 만들어지는 셈.
시험에 "START WITH를 생략하면?" 식으로 자주 나오는데, 답은 "에러는 안 나고, 결과 행이 늘어남"입니다.
4. 순환 참조(Cycle) 발생 시 ORA-01436
A의 상사가 B인데 B의 상사가 다시 A로 잡혀 있는 식의 데이터가 있으면 무한 순환에 빠집니다. 이때 CONNECT BY NOCYCLE을 추가하면 순환을 끊고 더 이상 안 내려가요. CONNECT_BY_ISCYCLE 의사컬럼으로 순환 행을 1로 표시할 수도 있고요.
5. ORDER BY를 그냥 쓰면 트리 순서가 깨진다
일반 ORDER BY를 쓰면 트리 깊이 순서가 무시되고 그냥 컬럼값으로 정렬됩니다. 트리 구조를 유지한 채 형제만 정렬하려면 ORDER SIBLINGS BY 를 써야 해요.
SELECT LEVEL, name
FROM EMP
START WITH mgr_id IS NULL
CONNECT BY PRIOR emp_id = mgr_id
ORDER SIBLINGS BY name; -- 같은 부모 밑에서만 이름순 정렬
시험장에서 푸는 순서
복잡한 계층형 질의 문제가 나오면 머리로 풀려고 하지 말고 손으로 그리세요. 5분 투자해도 아깝지 않아요. 1문제 놓치는 것보다 훨씬 쌉니다.
- 트리 그림부터 — 데이터를 보고 부모-자식 관계로 트리 그리기
- PRIOR 화살표 표시 — PRIOR 붙은 쪽이 기준이라는 걸 화살표로
- START WITH로 시작 노드 동그라미
- LEVEL 숫자 채우기 — 루트가 1, 한 단계 내려갈 때마다 +1
- WHERE 절은 마지막에 — 트리 다 만든 후에 가지치기만
요약 한 장
계층형 질의 핵심 5줄
- PRIOR 붙은 컬럼 = 이전 행의 그 컬럼 값. 화살표로 방향 잡기
- 평가 순서: START WITH → CONNECT BY → WHERE → SELECT
- WHERE로 노드 빼도 자식은 살아남음. CONNECT BY 안에 AND 넣으면 자식까지 잘림
- 의사컬럼 4개: LEVEL, CONNECT_BY_ROOT, CONNECT_BY_ISLEAF, SYS_CONNECT_BY_PATH
- 형제 정렬은 ORDER SIBLINGS BY (그냥 ORDER BY 쓰면 트리 깨짐)
이 5줄만 손으로 한 번 써보고 시험장 들어가면 계층형 질의 문제는 거의 다 잡힙니다. 시험 전날 마지막에 한 번 더 보는 정리노트로 쓰세요.