SQL

CTE(Common Table Expression)란?

dddzr 2025. 11. 29. 17:37

 

📌 1. CTE(Common Table Expression)란?

SQL에서 임시 결과 집합을 이름 붙여 재사용할 수 있는 쿼리


✔️ 장점

  • 쿼리를 읽기 쉽게 구조화 가능
  • 중복 쿼리 제거 → 유지보수 용이
  • 재귀 쿼리 구현 가능 (계층형/트리 구조)

📌2. CTE 문법

WITH cte_name AS (
    SELECT column1, column2
    FROM table_name
    WHERE condition

)

SELECT *
FROM cte_name;

 

✔️ 설명

  • WITH 뒤에 CTE 이름(cte_name) 지정
  • 괄호 안에 SELECT 문
  • 마지막에는 CTE를 사용하는 쿼리 필요

📌 3. 여러 CTE 연결

WITH
cte1 AS (
    SELECT 1 AS val
),
cte2 AS (
    SELECT val+1 AS val2
    FROM cte1
)

SELECT * FROM cte2;

 

 

✔️  콤마(,)로 여러 CTE를 나열 가능
⚠️  DB별 주의 사항

  • DB2, SQL Server, PostgreSQL, MySQL8.0 이상: 지원
  • MySQL < 8.0: CTE 지원 X → 서브쿼리로 대체

📌 4. 재귀 CTE

✔️ 목적

  • 트리 구조, 계층형 데이터 처리
  • 부모-자식 관계 등 반복 조회

📖 문법 예시 (DB2 / SQL Server / PostgreSQL)

WITH RECURSIVE menu_tree AS (
    -- 루트 메뉴
    SELECT menu_id, menu_name, '' AS parent_id, 1 AS lvl
    FROM menu
    WHERE parent_id IS NULL   
    UNION ALL    
    -- 하위 메뉴
    SELECT m.menu_id, m.menu_name, p.menu_id, p.lvl + 1
    FROM menu m
    JOIN menu_tree p ON m.parent_id = p.menu_id
)

SELECT * FROM menu_tree;

✔️ 루트: 계층의 시작점

✔️ UNION ALL: 하위 레벨과 합치기
✔️ 재귀 종료 조건: JOIN이 안 되는 경우 자동 종료

✔️ LVL로 깊이 관리 가능


📌 5. CTE 활용 예시

5-1. 중간 계산 결과 저장

WITH total_sales AS (
    SELECT employee_id, SUM(sale_amount) AS total
    FROM sales
    GROUP BY employee_id
)

SELECT *
FROM total_sales
WHERE total > 10000;
  • 복잡한 집계 쿼리를 분리해서 가독성 향상

5-2. 중복 제거 + 재사용

WITH recent_orders AS (
    SELECT order_id, customer_id
    FROM orders
    WHERE order_date > '2025-01-01'
)

SELECT c.customer_name, r.order_id
FROM customers c
JOIN recent_orders r ON c.customer_id = r.customer_id;
  • 서브쿼리 반복 제거

5-3. 계층형 조직도 조회

WITH RECURSIVE org_tree AS (
    SELECT emp_id, emp_name, mgr_id, 1 AS lvl
    FROM employee
    WHERE mgr_id IS NULL
    UNION ALL
    SELECT e.emp_id, e.emp_name, e.mgr_id, o.lvl + 1
    FROM employee e
    JOIN org_tree o ON e.mgr_id = o.emp_id
)

SELECT * FROM org_tree;

📌 6. 주의사항

✔️ 컬럼 개수 일치: UNION 또는 재귀 CTE에서는 루트와 하위 SELECT 컬럼 개수 + 타입 일치 필요

✔️ ORDER BY 사용 제한: CTE 내부에서는 ORDER BY 사용 X, 외부 SELECT에서 정렬

✔️ 재귀 CTE 종료 조건: 한 루프 주의 → JOIN 조건, 레벨 제한 필요

✔️ DB별 차이

  • DB2: RECURSIVE 생략 가능
  • MySQL/PostgreSQL: 반드시 WITH RECURSIVE
  • SQL Server: WITH만으로 재귀 가능

7️⃣ 요약

구분 특징 예시
기본 CTE 임시 테이블, 가독성 향상 WITH cte AS (SELECT ...) SELECT * FROM cte
여러 CTE 콤마로 연결 가능 WITH cte1 AS(...), cte2 AS(...) SELECT * FROM cte2
재귀 CTE 계층형 데이터 처리 WITH RECURSIVE cte AS (...) UNION ALL ...
주의 컬럼 개수, 타입, ORDER BY, DB별 문법 항상 확인 필요

 

💡 TIP

  • 재귀 CTE는 항상 루트 + 하위 SELECT가 컬럼 개수 동일해야 함
  • 복잡한 URL/파라미터 조합 같은 건 CTE 밖에서 처리하거나, 불필요하면 아예 제거

 

'SQL' 카테고리의 다른 글

JDBC / SQL Mapper / ORM (JPA, Hibernate, MyBatis)  (0) 2024.09.25