계층형 쿼리(Hierarchical Query)는 부모-자식 관계(트리 구조)를 가진 데이터를 조회하는 SQL 기법입니다. 일반적인 SQL 쿼리는 평면적(Flat) 데이터를 조회하는 반면, 계층형 쿼리는 트리 구조(Tree Structure)를 탐색할 수 있습니다.
예제:
SELECT [컬럼들]
FROM 테이블
START WITH [루트 조건]
CONNECT BY [계층적 관계 정의]
[ORDER SIBLINGS BY 컬럼명];
START WITH
: 계층 구조의 시작점을 지정CONNECT BY PRIOR
: 부모-자식 관계 정의ORDER SIBLINGS BY
: 동일한 부모를 가진 형제 노드들을 정렬테이블 구조
CREATE TABLE employees (
emp_id NUMBER PRIMARY KEY, -- 직원 ID
emp_name VARCHAR2(50), -- 직원 이름
manager_id NUMBER, -- 상사의 ID (NULL이면 최상위)
salary NUMBER -- 급여
);
데이터 샘플
INSERT INTO employees VALUES (1, 'Alice (CEO)', NULL, 10000);
INSERT INTO employees VALUES (2, 'Bob (Manager)', 1, 7000);
INSERT INTO employees VALUES (3, 'Charlie (Manager)', 1, 7000);
INSERT INTO employees VALUES (4, 'David (Staff)', 2, 5000);
INSERT INTO employees VALUES (5, 'Eve (Staff)', 2, 5000);
INSERT INTO employees VALUES (6, 'Frank (Staff)', 3, 4000);
INSERT INTO employees VALUES (7, 'Grace (Intern)', 4, 3000);
COMMIT;
데이터 구조
Alice (CEO) -- emp_id = 1 (최상위)
├── Bob (Manager) -- emp_id = 2, manager_id = 1
│ ├── David (Staff) -- emp_id = 4, manager_id = 2
│ │ ├── Grace (Intern) -- emp_id = 7, manager_id = 4
│ ├── Eve (Staff) -- emp_id = 5, manager_id = 2
├── Charlie (Manager) -- emp_id = 3, manager_id = 1
├── Frank (Staff) -- emp_id = 6, manager_id = 3
SELECT emp_id, emp_name, manager_id, LEVEL
FROM employees
START WITH manager_id IS NULL
CONNECT BY PRIOR emp_id = manager_id;
결과
EMP_ID | EMP_NAME | MANAGER_ID | LEVEL |
---|---|---|---|
1 | Alice (CEO) | NULL | 1 |
2 | Bob (Manager) | 1 | 2 |
4 | David (Staff) | 2 | 3 |
7 | Grace (Intern) | 4 | 4 |
5 | Eve (Staff) | 2 | 3 |
3 | Charlie (Manager) | 1 | 2 |
6 | Frank (Staff) | 3 | 3 |
LEVEL
: 트리 깊이를 나타냄 (CEO가 1, 그 아래 직원이 2, …)PRIOR emp_id = manager_id
: 부모(emp_id)가 자식(manager_id)과 연결됨START WITH manager_id IS NULL
: CEO(Alice)가 최상위 루트 노드임SELECT LPAD(' ', LEVEL * 4 - 4) || emp_name AS hierarchy, emp_id, manager_id
FROM employees
START WITH manager_id IS NULL
CONNECT BY PRIOR emp_id = manager_id;
결과
Alice (CEO)
Bob (Manager)
David (Staff)
Grace (Intern)
Eve (Staff)
Charlie (Manager)
Frank (Staff)
SELECT emp_id, emp_name, manager_id, LEVEL
FROM employees
START WITH manager_id IS NULL
CONNECT BY PRIOR emp_id = manager_id
ORDER SIBLINGS BY emp_name;
emp_name
기준으로 정렬됨.위 쿼리는 루트(CEO)부터 아래로 탐색하는 구조입니다.
하지만 특정 직원부터 아래 조직도를 보고 싶다면 START WITH
에서 지정합니다.
SELECT emp_id, emp_name, manager_id, LEVEL
FROM employees
START WITH emp_name = 'Bob (Manager)'
CONNECT BY PRIOR emp_id = manager_id;
결과 (Bob의 하위 직원만 조회)
EMP_ID | EMP_NAME | MANAGER_ID | LEVEL |
---|---|---|---|
2 | Bob (Manager) | 1 | 1 |
4 | David (Staff) | 2 | 2 |
7 | Grace (Intern) | 4 | 3 |
5 | Eve (Staff) | 2 | 2 |
CONNECT BY PRIOR manager_id = emp_id
를 사용하면 하위(자식) → 상위(부모) 탐색이 가능함.
SELECT emp_id, emp_name, manager_id, LEVEL
FROM employees
START WITH emp_name = 'Grace (Intern)'
CONNECT BY PRIOR manager_id = emp_id;
결과 (Grace의 상위 직원 조회)
EMP_ID | EMP_NAME | MANAGER_ID | LEVEL |
---|---|---|---|
7 | Grace (Intern) | 4 | 1 |
4 | David (Staff) | 2 | 2 |
2 | Bob (Manager) | 1 | 3 |
1 | Alice (CEO) | NULL | 4 |
SELECT emp_name, SYS_CONNECT_BY_PATH(emp_name, ' -> ') AS path
FROM employees
START WITH manager_id IS NULL
CONNECT BY PRIOR emp_id = manager_id;
결과
Alice (CEO)
-> Bob (Manager)
-> David (Staff)
-> Grace (Intern)
-> Eve (Staff)
-> Charlie (Manager)
-> Frank (Staff)
SELECT emp_name, CONNECT_BY_ROOT emp_name AS root_manager
FROM employees
START WITH emp_name = 'Frank (Staff)'
CONNECT BY PRIOR manager_id = emp_id;
결과
EMP_NAME | ROOT_MANAGER |
---|---|
Frank (Staff) | Alice (CEO) |
기능 | 설명 |
---|---|
START WITH | 트리의 시작점 지정 |
CONNECT BY PRIOR | 부모-자식 관계 설정 |
ORDER SIBLINGS BY | 같은 부모를 가진 형제 노드 정렬 |
SYS_CONNECT_BY_PATH | 전체 경로 출력 |
CONNECT_BY_ROOT | 루트(최상위) 찾기 |
Oracle의 계층형 쿼리는 조직도, 파일 시스템, 제품 카테고리 관리 등 다양한 실무에서 유용하게 활용됩니다. 🚀
윈도우 운영체제의 노트북에서는 iPhone 유선 테더링이 잘 안되는 경우가 많습니다. 보통 iPhone의 드라이버가 설치가 안되있어서인…
안녕하세요, 혹시 이런 생각해 본 적 없으신가요? "내가 투자한 회사는 누가 감시하고, 어떻게 운영될까?" 오늘은…
1. Gemini CLI란 무엇인가요? Gemini CLI는 터미널 환경에서 직접 Gemini 모델과 상호작용할 수 있도록 만들어진…
과적합은 머신러닝에서 학습용데이터를 과하게 학습하여, 실제데이터를 예측하지 못하는 현상을 말합니다. 인공지능(AI)의 학습 방법은 우리가 시험공부를…