
문제
https://school.programmers.co.kr/learn/courses/30/lessons/59413
프로그래머스
SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
문제 설명
- 보호소에서는 몇 시에 입양이 가장 활발하게 일어나는지 알아보려는 상황
- 0시부터 23시까지, 각 시간대별로 입양이 몇 건이나 발생했는지 조회하는 SQL문을 작성
- 결과는 시간대 순으로 정렬
정답 코드
WITH RECURSIVE hours AS (
SELECT 0 AS hour
UNION ALL
SELECT hour + 1
FROM hours
WHERE hour < 23
)
SELECT
h.hour AS HOUR,
COUNT(a.ANIMAL_ID) AS COUNT
FROM
hours h
LEFT JOIN
ANIMAL_OUTS a
ON HOUR(a.DATETIME) = h.hour
GROUP BY
h.hour
ORDER BY
h.hour
코드 설명
# 0부터 23까지의 시간(h)을 생성하는 재귀 CTE
WITH RECURSIVE hours AS (
SELECT 0 AS hour
UNION ALL
SELECT hour + 1 FROM hours WHERE hour < 23
)
- 0 ~ 23까지의 24개 시간을 가진 임시 테이블을 생성하기 위함
- 재귀적으로 hour 값을 1씩 증가시켜 23까지 생성
# 각 시간별 입양 횟수를 집계
SELECT
h.hour AS HOUR, -- 시간 (0~23)
COUNT(a.ANIMAL_ID) AS COUNT -- 해당 시간의 입양 건수
FROM
hours h
LEFT JOIN
ANIMAL_OUTS a
ON HOUR(a.DATETIME) = h.hour -- DATETIME 컬럼에서 시간 추출해 매칭
GROUP BY
h.hour
ORDER BY
h.hour
- ANIMAL_OUTS 테이블에서 DATETIME 컬럼의 시간 부분만 뽑아서 조인
- 예: 2025-07-18 14:32:10 → HOUR(DATETIME)는 14
- 왜 COUNT(*) 대신 COUNT(a.ANIMAL_ID)?
- ANIMAL_ID는 NOT NULL이므로, 입양이 없으면 NULL → COUNT는 0
- COUNT(*)도 작동하지만, LEFT JOIN 상황에서 NULL 행 포함될 수 있어 정확성에서 COUNT(a.컬럼)이 안전
참고) WITH RECURSIVE
- 재귀 CTE를 생성하는 구문으로, 쿼리가 자기 자신을 반복적으로 참조
- 반복적인 데이터 생성이나 계층적 관계 탐색에 사용됨
- 기본 구조
WITH RECURSIVE cte_name AS (
-- 초기 쿼리 (Base case)
SELECT ...
UNION ALL
-- 재귀 쿼리 (Recursive case)
SELECT ...
FROM cte_name
WHERE ...
)
SELECT * FROM cte_name
- WITH RECURSIVE: 재귀 CTE의 시작을 나타냄
- cte_name: CTE의 이름. CTE 내에서 정의된 데이터는 이 이름으로 참조할 수 있음
- UNION ALL: 기본 쿼리와 재귀 쿼리의 결과를 결합하는 데 사용됨. UNION을 사용하면 중복 제거가 발생하므로, UNION ALL을 사용하는 것이 효율적
첫 번째 시도 (실패)
SELECT HOUR(DATETIME) AS HOUR, COUNT(*) AS COUNT
FROM ANIMAL_OUTS
WHERE HOUR(DATETIME) BETWEEN 0 AND 23
GROUP BY HOUR(DATETIME)
ORDER BY HOUR(DATETIME)
- 입양 기록이 없는 시간대는 결과에 포함되지 않음 → 모든 시간대 테이블 생성 후 LEFT JOIN
'코딩 테스트 연습 > [프로그래머스][리트코드] MySQL' 카테고리의 다른 글
| [LV.5] String, Date > 자동차 대여 기록 별 대여 금액 구하기 ⭐️ (5) | 2025.07.24 |
|---|---|
| [LV.5] JOIN > 특정 기간동안 대여 가능한 자동차들의 대여비용 구하기 ⭐️ (2) | 2025.07.22 |
| [LV.5] SELECT > 조건에 부합하는 중고거래 댓글 조회하기 (1) | 2025.07.16 |
| [LV.5] SELECT > 오프라인/온라인 판매 데이터 통합하기 ⭐️ (2) | 2025.07.14 |
| [LV.5] JOIN > 그룹별 조건에 맞는 식당 목록 출력하기 ⭐️ (4) | 2025.07.11 |