[MySQL] 재귀적 표현식

niz w·2025년 1월 23일

SQL

목록 보기
14/17

프로그래머스 SQL 문제를 풀다가 재귀적 표현을 봤다.
로직 짤 때도 알고 있지만 쉽게 쓰지 않던 부분인데... SQL에도 있다니;;;




1. RECURSIVE

WITH로 쿼리에서 따로 활용할 테이블? 뷰?를 설정해주게 되는데
여기에서 RECURESIVE를 써주면 자기 자신을 반복 호출하여 계층형 데이터를 조회할 수 있다.
보통 트리 구조의 데이터를 다룰 때 유용하다.

-- 기본 문법
WITH RECURSIVE [이름] AS (
	기본 쿼리 (재귀가 시작할 점)
    UNION ALL
    재귀 쿼리 (자기 자신 활용)
)
SELECT * FROM [이름];

위의 형식으로 사용하게 된다.




2. 예시

WITH RECURSIVE TIME AS(
    SELECT 0 AS HOUR
    UNION ALL
    SELECT HOUR + 1
        FROM TIME
        WHERE HOUR < 23
)
SELECT * FROM TIME;

이렇게 사용하면 0~23 까지는 숫자가 출력된다.



id name manager_id
1 Kim NULL
2 Bob 1
3 Amy 1
4 Dave 2
5 Eve 2
WITH RECURSIVE employee_hierarchy AS (
    SELECT id, name, manager_id, 1 AS level
    FROM employees
    WHERE id = 2

    UNION ALL

    SELECT e.id, e.name, e.manager_id, eh.level + 1
    FROM employees e
    JOIN employee_hierarchy eh ON e.manager_id = eh.id
)
SELECT * FROM employee_hierarchy;

=> 출력결과

id name manager_id level
2 Bob 1 1
4 Dave 2 2
5 Eve 2 2

주어진 테이블에서 직원과 각자의 maneger가 매칭된 데이터가 있다고 하자.
여기서 Bob의 부하 직원들 내역을 뽑고 싶다.
따라서 Bob에게는 level1을 부여하고 Bob을 manager로 둔 직원들을 뽑아 level2로 계층까지 출력을 해주었다.



만약 테이블이 아래와 같이 바뀌어서 Bob의 바로 아래 부하직원에게도 부하직원이 있다면??

id name manager_id
1 Kim NULL
2 Bob 1
3 Amy 1
4 Dave 2
5 Eve 2
6 Frank 3
7 Alice 4
8 Charlie 4

부하직원의 부하직원까지 같은 라인?에 해당하는 직원들이 아래와 같이 출력될 것이다.

id name manager_id level
2 Bob 1 1
4 Dave 2 2
5 Eve 2 2
7 Alice 4 3
8 Charlie 4 3


🚨무한 루프 방지!!

위의 경우는 데이터 제한이 있어 종료되지만...
만약 상수를 끊임없이 뽑아내는 경우 무한루프를 돌게 된다.

WITH RECURSIVE TIME AS(
    SELECT 0 AS HOUR
    UNION ALL
    SELECT HOUR + 1
        FROM TIME
        WHERE HOUR < 23
)
SELECT * FROM TIME;

제일 처음 주어진 쿼리에서 처럼 HOUR<23의 조건을 주거나
직원 계층을 뽑는 경우라면 LEVEL로 제한을 두어 해당 부분까지만 진행되도록 하는 것이 좋다!!

0개의 댓글