Tools/- SQL

[SQL] 📌 recursive (재귀쿼리) 알아보기 | 프로그래머스 예제 | 멸종위기의 대장균 찾기 | level 5

스위민 2025. 3. 6. 22:52

재귀쿼리(recursive)란?

재귀함수 함수 안에 자신의 함수를 다시 호출하는 함수이다. 

재귀함수는 자신의 로직을 내부적으로 반복하다가, 일정한 조건이 만족되면 함수를 이탈하여 결과를 도출한다.

 

 

재귀쿼리(recursive) 문법

  • WITH RECURSIVE 문
1. with문 :
∙ 재귀쿼리는 꼭 with문 안에 넣어줘야 한다.
∙ 일반 with문과 다르게 cte앞에 'recursive'를 적어줘야 한다  ( ex: with recursive cte as )

2. 비반복문 (Non-Recursive) select 문 :
∙재귀쿼리의 일종의 root을 만들어줘야 한다.  ( i = i + 1을 반복할 때, root로 i = 1을 심어주는 것 )

3. union all
∙ root와 반복할 쿼리를 합쳐준다.

4. 반복문 (Recursive) select 문
∙ 반복할 부분을 쿼리로 작성해준다. ( ex. i = i + 1 )
∙ 반드시 정지조건을 넣어줘야한다 ! 아니면 무한루프에 빠질지도 ...  ( ex. i (반복할 변수) < 25 )

 

 

프로그래머스 예제

https://school.programmers.co.kr/learn/courses/30/lessons/301651

 

 

쿼리

with recursive cte as
    (select 1 as generation, id -- 비반복문 (root)
     from ecoli_data 
     where parent_id is null
     
    union all -- 비반복문과 반복문을 union해준다
    
    select generation + 1, b.id -- 반복문
    from cte a
    join ecoli_data b
    on a.id = b.parent_id)

select count(id) as count, generation
from cte
where id not in (select distinct parent_id from ecoli_data where parent_id is not null) -- 왜 parent_id를 not null 해줘야 할까
group by generation
order by generation

-- NULL 값 비교 시 NOT IN이 의도와 다르게 동작 가능

 

 

문제풀이

recursive cte :

각 ID가 어떤 세대에 해당하는지 먼저 구해줘야 한다.이를 구하기 위해 재귀함수를 사용해준다.그러면 마지막 세대인 4세대를 구할 때까지 반복되다 멈춘다.그러면 generation, id로 구성된 테이블을 구할 수 있다!

 

이제 cte를 불러와서 각 세대별 자식이 없는 id를 count해주면 된다.

 

여기서 주의할 점은 not in을 사용할 때 비교할 서브쿼리에 null값이 있으면 not in 기능이 제대로 동작하지 않는다는 것이다!

 

 

느낀 점

이 문제의 포인트는 recursive(재귀함수) 사용과 not in 사용 조건을 아는 것이다.그리고 self join할 때 어떤 테이블의 부모 ID와 자식 ID를 비교해서 가져올 건지 잘 구상해야 한다.