본문 바로가기
PS/SQL

[프로그래머스] 특정 세대의 대장균 찾기

by 행복한라이언 2024. 5. 2.
728x90
반응형

문제링크

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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

1. 핵심

- WITH RECURSIVE [] AS ( ) 에 대한 이해!! (디버깅하면서 이해한거라 틀릴 수 있음)

- non recursive 부분 : tree 테이블의 기초가 되는 부분이다.

-- non recursive 부분 : tree 테이블의 기초가 되는 부분이다.
-- ECOLI_DATA 에서 PARENT NULL 제외한 것.
-- ID, PARENT_ID, GE 의 기초가 세팅

select  ID, PARENT_ID, 2 as GE
    from ECOLI_DATA
    where PARENT_ID is not null

 

기초 셋팅 테이블

 

- recursive 부분: 반복이 발생하는 부분으로 tree 테이블에 계속 붙는다.

    -- recursive
    select C.ID, C.PARENT_ID, T.GE + 1 
    from ECOLI_DATA as C
    inner join tree as T on C.PARENT_ID = T.ID

 

- 반복 1번: '기초 셋팅 테이블'과 ECOLI_DATA INNER JOIN 한다.

-  기초 셋팅 테이블(T) 의 ID에는 3 ~ 8 만 존재한다. 따라서 ECOLI_DATA(C) 의 PARENT_ID와 JOIN을 한다. 

- C.ID 중 PARENT_ID가 3 ~ 8을 가지는 C.ID는 6 ~ 8 만 있다. 그래서 6 ~ 8 ID을 갖는 JOIN 테이블이 형성된다.

반복 1번 조인 테이블
반복 1번한 후 tree 결과 테이블

- 반복 2번: '반복 1번 조인 테이블' 과 ECOLI_DATA(C) INNER JOIN 한다.

- 디버깅을 해본 결과 갱신된 '반복 1번한 후 tree의 테이블'과 JOIN이 발생하지 않는다. JOIN은 '반복 1번 조인 테이블' 과  발생한다.

- '반복 1번 조인 테이블' 에는 ID가 6 ~ 8 을 갖는다.

- 따라서 ECOLI_DATA(C) 에서 PARENT_ID를 6 ~ 8 를 갖는 C.ID는 6 하나이다.  그래서 반복2번 조인 테이블이 생성된다.

반복 2번 조인 테이블

- recursive 종료

- 반복2번 조인테이블이 갖는 ID는 8이다. ECOLI_DATA(C) 에서 PARENT_ID을 8을 갖는 경우가 없기 때문에 반복문 종료된다.

 

- 최종결과: 만들어진 조인 테이블이 union all 된 상태로 출력된다.

 

- 각 ID의 세대를 알기 위해서 ID로 GROUP BY 묶으 후 MAX(GE) / HAVING절로 3세대 체크 / ID로 오름차순

2. 코드(MySQL)

with recursive tree as (
    -- non recursive
    select  ID, 
            PARENT_ID,
            2 as GE
    from ECOLI_DATA
    where PARENT_ID is not null
    
    union all
    
    -- recursive
    select C.ID, C.PARENT_ID, T.GE + 1 
    from ECOLI_DATA as C
    inner join tree as T on C.PARENT_ID = T.ID
)

select ID
from tree
group by ID
having(max(GE) = 3)
order by ID asc;

 

3. 활용예제

with recursive rc as (
-- non recursive
  select 1 as hour
  union all
-- recursive
  select hour + 1 
  from rc 
-- terminate
  where hour < 5 
)

select * from rc

/*
1
2
3
4
*/
728x90
반응형