SQL

[SQL] 재귀 CTE(Recursive CTE)

주댕이 2025. 4. 10. 16:02

재귀 CTE트리 구조나 계층형 데이터를 다룰 때 매우 유용한 기능이다. 특히 부모-자식 관계 데이터를 탐색할 때 많이 사용한다.

CTE (Common Table Expression)

WITH CTE_NAME AS (
	SELECT ...
)
SELECT * FROM CTE_NAME;
  • 쿼리 안에서 임시로 사용하는 테이블
  • 가독성을 높이고, 서브쿼리를 반복하지 않을 수 있게 한다.

📍 CTE에 대해 자세히 알아보기

 

재귀 CTE (Recursive Common Table Expression)

재귀 CTE는 자기 자신을 참조하는 CTE이다. 한 번 재귀 CTE를 실행하면, 내부적으로 반복(루프)을 통해 레코드를 점진적으로 확장한다.

구조

재귀 CTE는 두 부분으로 나누어진다:

  1. Anchor Member (기저 멤버)
    • 재귀가 시작되는 출발점
    • 보통 PARENT_ID IS NULL처럼, 트리 구조의 루트 노드를 찾는 쿼리이다.
  2. Recursive Member (재귀 멤버)
    • Anchor의 결과를 입력으로 받아 자기 자신을 반복적으로 호출
    • JOIN을 통해 부모와 자식 간의 관계를 이어가는 쿼리이다.

이 둘은 UNION ALL을 통해 묶인다.

WITH RECURSIVE CTE_NAME AS (
    -- ① Anchor Member
    SELECT ... FROM 테이블 WHERE 조건

    UNION ALL

    -- ② Recursive Member
    SELECT ... FROM 테이블
    JOIN CTE_NAME ON 연결 조건
)
SELECT * FROM CTE_NAME;

 

내부 동작 원리

재귀 CTE는 내부적으로 다음과 같은 방식으로 작동한다.

  1. Anchor Member 쿼리가 실행되어 초기 결과 세트 생성 (Generation 1)
  2. Recursive Member가 Anchor 결과와 JOIN되어 다음 세대 생성
  3. 새로 생성된 결과를 다시 Recursive Member에 투입하여 JOIN 반복
  4. 더 이상 결과가 나오지 않을 때까지 반복 (종료 조건 만족)

즉, CTE_NAME은 마치 누적되는 임시 테이블처럼 동작하며, 세대가 하나씩 늘어나는 방식으로 데이터가 전개된다.

 

UNION ALL을 써야 하는 이유

UNION은 중복 제거를 수행하기 때문에 성능 저하불필요한 오버헤드가 발생할 수 있다. 재귀 CTE에서는 일반적으로 중복을 신경 쓰지 않으므로 UNION ALL을 사용하는 것이 좋다.

 

재귀 종료 조건

재귀 CTE는 암묵적으로 더 이상 JOIN될 데이터가 없을 때 종료된다.
하지만 실수로 종료 조건이 누락되거나 루프 구조가 잘못되면, 무한 루프나 성능 저하가 발생할 수 있기 때문에, 명시적인 종료 조건을 재귀 멤버 안에 넣는 것이 좋다.

  • 예시
WHERE GENERATION <= 5 -- 최대 5세대까지만 조회

 



 

728x90

'SQL' 카테고리의 다른 글

[SQL] 비트 연산  (0) 2025.04.01
[SQL] SQL 정규 표현식 (SQL Regular Expression)  (0) 2025.01.12
[SQL] 가독성 높이기  (0) 2025.01.08
[SQL] INSTR()  (0) 2024.12.19
[SQL] SUBSTR()  (0) 2024.12.19