MYSQL) Recursive 문법

kiki·2024년 8월 7일
0

기본기

목록 보기
7/9

sql에서 재귀를 쓰는 방법이다!

나는 해당 문제를 풀 때, 하드코딩(?)을 사용했는데 다른 사람들이 푼 걸 보니 재귀를 사용하길래 찾아봤다.

WITH RECURSIVE CTE (CNT) AS(
	SELECT 1 
    
    UNION ALL
    
    SELECT CNT+1
    FROM CTR
    WHERE CNT<4
)

SELECT *
FROM CTE;

기본 구조는 위와 같다.
UNION ALL 윗 부분이 비재귀 부분이며 초기값을 설정한다.
UNION ALL을 통해서 위와 아래 쿼리를 엮어준다.
UNION ALL의 아래 부분이 재귀 부분이며 WHERE의 조건을 만족하는 동안 반복해 진행한다.

초 심플 !
예시는 항상 쉽지..

실제 사용한 재귀 쿼리

WITH RECURSIVE R AS (
    SELECT ID, PARENT_ID, 1 AS GEN
    FROM ECOLI_DATA
    WHERE PARENT_ID IS NULL

    UNION ALL

    SELECT A.ID, A.PARENT_ID, R.GEN+1 AS GEN
    FROM ECOLI_DATA A
    JOIN R ON A.PARENT_ID = R.ID
)

내가 하고싶었던 건 parent id를 사용해 각 레코드의 세대를 구하고 싶었다.
그러기 위해선 1세대 부터 시작해 parent id를 이용해 join하고 gen+1을 통해 세대를 구해야했다.

그래서 비재귀 부분에 PARENT_ID가 NULL값인, 즉 1세대인 데이터만을 SELECT 했고,
재귀 부분에서 원본 데이터를 재귀 데이터(?)와 조인해 1세대의 자식 데이터만 SELECT해 GEN을 1씩 증가해줬다.

이렇게 하면 모든 데이터에 대해 세대를 계산할 수 있게된다!


여기서 키포인트는 INNER JOIN을 사용해서 원본 데이터에서 자식 레코드만 SELECT한다는 점인 것 같다. (근데 재귀로 하다보면 계속해서 선택되는 레코드가 있지 않나? 그건 어떻게 처리되는거지?)

*JOIN의 디폴트는 INNER JOIN이라는 점...! 계속 까먹는데 잊지 말자.

UNION ALL이 뭐였더라...

UNION ALL은 두 쿼리의 결과를 수직으로 합치는 것이다.

여기서 UNION은 두 쿼리 결과에서 중복되는 레코드를 제거하며,
UNION ALL은 중복되는 레코드 모두 제거하지 않고 합친다.

그렇기 때문에 UNION ALL이 UNION보다 빠른 실행 속도를 보임
하지만 이를 사용하는건 장기적으론 좋지 않음. 모델링 차원에서 테이블을 통합하는게 좋다고 한다!

0개의 댓글