자신에게 친절할 것 :)

Data Science/MySQL

[프로그래머스 sql] 트리구조에서 cte recursive, 리프 노드

Tashapark 2025. 2. 19. 16:35
728x90
반응형

멸종위기의 대장균 찾기

 

- 아니 무슨 대장균 찾기의 끝이 없냐...

 

 

수정 전 

- 방금 전 한 대로 cte recursive 를 써보려는 데 런타임 에러가 뜸...

- 또, cte에서는 not in을 쓸 수 없대. 

WITH RECURSIVE GEN AS (
    SELECT ID, 
        1 AS GENERATION
    FROM ECOLI_DATA
    WHERE PARENT_ID IS NULL -- 1세대 
    
    UNION ALL
    
    SELECT A.ID, B.GENERATION + 1 AS GENERATION
    FROM ECOLI_DATA A, GEN B
    WHERE A.PARENT_ID NOT IN (B.ID)
)

SELECT COUNT(ID) AS COUNT, GENERATION
FROM GEN
GROUP BY GENERATION
ORDER BY GENERATION;

 

수정 후 1

- parent_id 가 있어야 select 시 조건 부여 가능 

WITH RECURSIVE GEN AS (
    SELECT ID, PARENT_ID,
        1 AS GENERATION
    FROM ECOLI_DATA
    WHERE PARENT_ID IS NULL -- 1세대 
    
    UNION ALL
    
    SELECT A.ID, B.GENERATION + 1 AS GENERATION
    FROM ECOLI_DATA A, GEN B
    WHERE A.PARENT_ID = B.ID
)

SELECT COUNT(ID) AS COUNT, GENERATION
FROM GEN
GROUP BY GENERATION
having PARENT_ID != ID
ORDER BY GENERATION;

 

수정 후 2

- cte 두 조건 식 모두에 출력 값을 넣어줘야 함. 

- 이렇게 해도 실패..

- having은 집계 함수만 넣을 수 있음. 

WITH RECURSIVE GEN AS (
     -- (1) 최상위 노드 (1세대)
    SELECT ID, PARENT_ID,
        1 AS GENERATION
    FROM ECOLI_DATA
    WHERE PARENT_ID IS NULL -- 1세대 
    
    UNION ALL
    
    -- (2) 부모-자식 관계를 따라가며 세대(GENERATION) 증가
    SELECT A.ID, A.PARENT_ID, B.GENERATION + 1 AS GENERATION -- 여기도 조건 넣어야 함
    FROM ECOLI_DATA A, GEN B
    WHERE A.PARENT_ID = B.ID
)

-- 세대별 개수 계산 (부모-자식 관계가 다른 경우만 포함)
SELECT COUNT(ID) AS COUNT, GENERATION
FROM GEN
WHERE PARENT_ID != ID -- having은 집계 시에만 사용 
GROUP BY GENERATION
ORDER BY GENERATION;

 

======= 여기까지 하다가 안 되겠어서 다른 분들 답변을 봤는데

left join을 사용한 경우가 많았는데

이해가 안가서 gpt에게 물어봤음.

 

수정 후 3

- 자식 노드가 없는 대장균 count = leaf node 카운트

- leaf node : 자식 노드가 없는 끝 노드

 

... 자료 구조를 잘 알고 있어야 활용이 가능한 듯.. 공부 좀 하자.. 진짜..

so, left join으로 자식이 있는 값은 값 들어가고 없으면 null 뜨게 해서

리프 노드만 count 하는 방법으로 구성하심..

천재인가..

 

.. 보고 따라 써보긴 했는데 쓰면서도.. 좀 이해가 안감..

굳이 조인을 해야 하는 건가..

 

- 어떤 경우는 join으로 합치고 어떤 경우는 아닌 것을 확실히 할 수가 없네. 

WITH RECURSIVE GEN AS (
     -- (1) 최상위 노드 (1세대)
    SELECT ID, 
        1 AS GENERATION
    FROM ECOLI_DATA
    WHERE PARENT_ID IS NULL -- 1세대 
    
    UNION ALL
    
    -- (2) 부모-자식 관계를 따라가며 세대(GENERATION) 증가
    SELECT A.ID, B.GENERATION + 1 AS GENERATION 
    FROM ECOLI_DATA A
    JOIN GEN B ON A.PARENT_ID = B.ID -- 자식 노드 있는 얘들 
)

-- 세대별 개수 계산 (부모-자식 관계가 다른 경우만 포함)
SELECT COUNT(*) AS COUNT, G.GENERATION
FROM GEN G
LEFT JOIN ECOLI_DATA C ON G.ID = C.PARENT_ID
WHERE C.ID IS NULL -- 리프 노드 
GROUP BY GENERATION
ORDER BY GENERATION;

 

728x90
반응형