코딩테스트

[26.03.26 코테/회고(MySQL/Oracle)]-입양 시각 구하기(2)

지니248 2026. 3. 26. 18:40

Lv4. 입양 시각 구하기(2) (MySQL)

링크: https://school.programmers.co.kr/learn/courses/30/lessons/59413?language=mysql

 

내가 작성한 코드

WITH RECURSIVE HOUR_TABLE(HOUR) AS (
    SELECT 0 AS HOUR -- 초기값 설정(0시)
    UNION ALL
    SELECT HOUR + 1 
    FROM HOUR_TABLE
    WHERE HOUR < 23 -- 23시가 될 때까지 1씩 증가하며 반복
)
SELECT H.HOUR, COUNT(O.ANIMAL_ID) AS COUNT
FROM HOUR_TABLE H
LEFT JOIN ANIMAL_OUTS O
       ON H.HOUR = HOUR(O.DATETIME) -- 가상 데이터와 실제 데이터 시간 조인
GROUP BY H.HOUR
ORDER BY H.HOUR;

 

Oracle

WITH HOUR_TABLE(HOUR) AS (
    -- 시작점 설정
    SELECT 0 FROM DUAL
    UNION ALL
    -- 재귀 호출
    SELECT HOUR + 1 
    FROM HOUR_TABLE
    WHERE HOUR < 23
)
SELECT H.HOUR, COUNT(O.ANIMAL_ID) AS COUNT
FROM HOUR_TABLE H
LEFT JOIN ANIMAL_OUTS O
       ON H.HOUR = TO_NUMBER(TO_CHAR(O.DATETIME, 'HH24'))
GROUP BY H.HOUR
ORDER BY H.HOUR;

문제 회고

1. 재귀 WITH절 (Recursive CTE)

- 재귀로 풀어야 한다는 방법을 몰라 계속 오류가 발생했다

- 다른 분들께서 푸신 방식들을 통해 해결 방법을 알게 되었다

- 해결 방법:

   - 입양 기록이 없는 시간대도 결과에서 누락되지 않게 0시부터 23시까지의 가상 시간대 테이블을 먼저 생성해야함을 배웠다

   - 초기값 설정 : SELECT 0을 통해 시작점인 0시를 설정한다

   - 반복(Recursive) : UNION ALL과 SELECT HOUR + 1을 사용하여 자기 자신을 참조하며 숫자를 1씩 증가시킨다

   - 정지 : WHERE 절에 종료 조건인 HOUR < 23을 명시하여 무한루프를 방지하고 문제에 맞는 필요한 범위(0~23)를 생성한다

2. LEFT JOIN

- 생성한 가상 테이블(HOUR_TABLE)을 왼쪽에 두고 실제 데이터(ANIMAL_OUTS)를 LEFT JOIN하여

  기록이 없는 시간대도 결과 행에 유지되도록 처리한다

- 조인된 컬럼의 테이블인 COUNT(O.ANIMAL_ID)를 사용하여 데이터가 없는 시간대의 건수가 정확히 0이 나오도록 한다

3. 재귀 표현 방식의 차이점

- MySQL : SELECT 0 AS HOUR 처럼 내부에 별칭을 주면 (HOUR)을 생략해도 실행된다

- Oracle : WITH 테이블명(컬럼명) 형식을 지켜야한다. 컬럼명을 명시하지 않으면 재귀 부분에서 이전 단계의 값을 참조할 수 없다

               : Oracle은 WITH절 안에 UNION ALL이 있으면 자동으로 재귀로 인식하여 RECURSIVE 키워드를 빼도 된다