오늘은 SQL에서 자주 보이는 CTE를 공부했다.
처음엔 그냥 WITH 쓰는 문법 정도로만 알았는데, 정리해보니 생각보다 구조적으로 중요한 개념이었다.
CTE는 Common Table Expression의 약자이고
WITH 절을 사용해서 임시 결과 집합에 이름을 붙이는 것이다.
기본 구조는 이렇게 생겼다.
WITH cte_name AS (
SELECT ...
)
SELECT *
FROM cte_name;
처음엔 “굳이?” 싶었는데
복잡한 쿼리를 작성해보니까 이유를 알겠음.
특히 집계 쿼리에서 진짜 편하다.
WITH avg_salary AS (
SELECT department_id, AVG(salary) AS avg_sal
FROM employees
GROUP BY department_id
)
SELECT e.employee_name, e.salary
FROM employees e
JOIN avg_salary a
ON e.department_id = a.department_id
WHERE e.salary > a.avg_sal;
1단계: 부서별 평균 계산
2단계: 평균보다 큰 사람만 조회
이렇게 나누니까 쿼리 읽기가 훨씬 편했다.
같은 문제를 서브쿼리로도 작성해봤다.
SELECT employee_name, salary
FROM employees e
WHERE salary > (
SELECT AVG(salary)
FROM employees
WHERE department_id = e.department_id
);
| 구분 | CTE | 서브쿼리 |
|---|---|---|
| 가독성 | 좋음 | 중첩되면 복잡 |
| 구조화 | 단계 분리 가능 | 한 번에 들어감 |
| 재사용 | 가능 | 거의 불가능 |
| 재귀 | 가능 | 불가능 |
개인적으로는
로직이 복잡해질수록 CTE가 훨씬 낫다고 느낌
조직도 같은 계층형 데이터를 처리할 때 사용한다.
WITH RECURSIVE hierarchy AS (
SELECT employee_id, manager_id
FROM employees
WHERE manager_id IS NULL
UNION ALL
SELECT e.employee_id, e.manager_id
FROM employees e
JOIN hierarchy h
ON e.manager_id = h.employee_id
)
SELECT * FROM hierarchy;
아직 완전히 익숙하진 않지만
CTE가 단순 가독성 개선용이 아니라는 걸 알게 됐다.
앞으로 쿼리 작성할 때
무조건 한 번에 쓰기보다
단계적으로 분리하는 연습을 해야겠다.