coding/sql 코딩테스트

[프로그래머스] 멸종위기의 대장균 찾기

임이레 2025. 1. 6. 19:21

코딩테스트를 풀며 재귀쿼리를 처음 보았다. 우선 잘 모르는 쿼리 문법이기에 다른 분의 쿼리를 보며 뜯어보고 이해하는 과정을 거쳤다. 

이렇게 SQL 코딩테스트에서 만점을 받는 미래의 나를 상상한다. 

 

우선 재귀 쿼리란 

데이터베이스에서 자기 참조 데이터 또는 계층적 데이터를 조회할 때 사용되는 쿼리라고 한다. MySQL 에서는 WITH RECURSIVE 라는 키워드를 사용해 재귀 쿼리를 작성할 수 있고 이번 문제 또한 이 문법을 활용해서 작성하였다.
이를 통해 부모-자식 관계를 갖는 계층적 데이터를 작성하고 추출할 수 있다.

 

WITH RECURSIVE CTE (컬럼1, 컬럼2, ...) AS 
( SELECT 
  FROM 
  WHERE 
  
  UNION ALL 
  
  --- 재귀적으로 호출되어야 하는 부분을 작성한다. 
  SELECT 
  FROM 
  JOIN CTE ON 
  
  ) 
  
  SELECT * 
  FROM CTE ;

 

 

WITH RECURSIVE GenerationCTE AS (
    SELECT ID 
         , PARENT_ID 
         , 1 AS Generation 
    FROM ECOLI_DATA 
    WHERE PARENT_ID IS NULL

- PARENT_ID IS NULL 이라는 조건을 통해 루트 노드(최상위 계층)를 가져온다.

- Generation 은 세대로 1로 시작

 

    UNION ALL 
    
    SELECT e.ID, e.PARENT_ID, g.Generation + 1 as Generation 
    FROM ECOLI_DATA e 
    JOIN GenerationCTE g ON e.PARENT_ID = g.ID
)

- JOIN GenerationCTE g ON e.PARENT_ID = g.ID 는 자식노드를 부모 노드와 연결하여 다음 계층으로 확장하도록 한다. 

** Generation + 1 을 하여 각 자식 노드의 세대를 하나씩 증가시키는 컬럼을 추가한다. ** 

 

WHERE ID NOT IN (
        SELECT DISTINCT parent_id 
        FROM GenerationCTE
        WHERE parent_id IS NOT NULL)

 

조건은 parent_id 가 NULL 이 아닌 parent id 를 1차적으로 거른 후 parent_id 가 있는 ID 는 제외한다. 

이렇게 되면, 어떤 노드의 부모로도 등장하지 않은 노드를 선택할 수 있게 된다. 

 

마지막으로 각 세대별로 COUNT 를 수행한다. 

SELECT COUNT(*) AS COUNT, Generation 
FROM GenerationCTE 
GROUP BY Generation 
ORDER BY 2

 

전체 코드 

-- 코드를 작성해주세요

WITH RECURSIVE GenerationCTE AS (
    SELECT ID 
         , PARENT_ID 
         , 1 AS Generation 
    FROM ECOLI_DATA 
    WHERE PARENT_ID IS NULL
    
    UNION ALL 
    SELECT e.ID , e.PARENT_ID , g.Generation + 1 as Generation 
    FROM ECOLI_DATA e 
    JOIN GenerationCTE g ON e.PARENT_ID = g.ID)


SELECT count(*) as COUNT 
        , Generation 
FROM GenerationCTE 
WHERE ID not in (
        select distinct parent_id 
        from GenerationCTE
        where parent_id is not null)
GROUP BY generation 
order by 2

 

 

혼자 작성하진 못하고 재귀 쿼리 답변을 보며 뜯어봄으로 이해를 완료하였다. 바로 내일 동일한 문제를 스스로 풀어보며 체화시켜야겠다!