SQL 관련 모든 문제들은 MySQL을 기준으로 해결했다.
이번 문제는 프로그래머스 SQL 문제 중에 가장 어렵기도 했고, 새로운 계층 쿼리를 배울 수 있는 문제였다.
사실 처음에는 이전 문제와 동일하게 HOUR 함수를 사용해 풀었는데 아래와 같이 출력됐다.
문제를 다시 읽어보면 0시부터 23까지 출력을 하라고 했는데 위에서는 7시부터의 데이터가 출력된다. 0~6시까지는 COUNT가 0이라서 출력되지 않고 있었던 것이다.
해결 방법을 잘 모르겠어서 다른 분들의 풀이를 참고했고, 재귀 쿼리 방법을 발견했다.
RECURSIVE
를 이용해 0~23시까지를 보여주는 가상의 시간 테이블을 생성하고 이 테이블을 참고해 데이터를 출력하는 방법이다.
WITH RECURSIVE(재귀) 쿼리 계층구조
- 메모리 상에 가상의 테이블을 저장
- 재귀 쿼리를 이용해 실제로 테이블을 생성하거나 데이터 삽입(INSERT)을 하지 않아도 가상 테이블 생성 가능
- 가상의 테이블을 생성하면서 가상 테이블 자신의 값을 참조하여 값을 결정할 때 유용
- 반드시 UNION 사용
- 반드시 비반복문(Non-Recursive)도 최소한 1개 필수. 처음 한 번만 실행
- 바깥의 가상 테이블을 참조하는 문장(반복문)이 반드시 필요
WITH RECURSIVE 테이블명 AS( SELECT 초기값 AS 컬럼별명 # 비반복문(Non-Recursive). 필수. 처음 한 번만 실행 UNION ALL # RECURSIVE 사용 시 필수. 다음에 이어붙어야 할 때 사용 SELECT 컬럼별명 계산식 FROM 테이블명 # 반복문(Recursive). WHERE 제어문 # RECURSIVE 사용 시 필수. 정지 조건 필요할 때 사용 )
# 가상 테이블 생성(테이블명 : SECOND_TABLE)
WITH RECURSIVE SECOND_TABLE AS(
SELECT 0 AS HOUR # HOUR의 초기값을 0으로 설정
UNION ALL
SELECT HOUR+1 FROM SECOND_TABLE WHERE HOUR < 23 # HOUR가 23 미만일 때까지 반복
)
SELECT SECOND_TABLE.HOUR, COUNT(ANIMAL_ID)
FROM SECOND_TABLE
LEFT OUTER JOIN ANIMAL_OUTS
ON HOUR(DATETIME) = SECOND_TABLE.HOUR
GROUP BY SECOND_TABLE.HOUR
ORDER BY SECOND_TABLE.HOUR;
문제 출처 : https://programmers.co.kr/learn/courses/30/lessons/59413