코딩테스트/SQL

[프로그래머스][MySQL] Lv. 4 입양 시각 구하기(2)

_알파카 2024. 8. 12. 17:25
728x90

문제 설명

https://school.programmers.co.kr/learn/courses/30/lessons/59413

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

단순히 GROUP BY를 해서는 풀지 못하는 문제이다. 

GROUP BY를 하면 일부의 시간만 출력되고 모든 시간이 출력되지는 않기 때문이다. 

즉, 문제에서는 0시부터 23시까지 값이 없는 데이터도 출력하라 하였는데, 

데이터가 없는 시간이 존재한다! 

파이썬으로 하면 쉽게 할 수 있을 것 같은데, 좀 어려웠다ㅠㅠ

그래서 다른 사람의 풀이를 보고 풀어보았다. 

 

풀이

-- RECURSIVE CTE
WITH RECURSIVE CTE AS(
    SELECT 0 AS NUM
    UNION ALL
    SELECT NUM +1
    FROM CTE
    WHERE NUM < 23
)
SELECT CTE.NUM HOUR, COUNT(HOUR(O.DATETIME)) AS COUNT 
-- COUNT(*)으로 하면 데이터 없는 ROW도 1로 CNT 하므로 COUNT(HOUR(O.DATETIME)) 사용
FROM ANIMAL_OUTS O RIGHT OUTER JOIN CTE
ON HOUR(O.DATETIME) = CTE.NUM
GROUP BY CTE.NUM
ORDER BY CTE.NUM

 

위는 Recursive CTE (재귀 CTE)를 사용한 풀이이다. 

재귀 CTE는 일반적인 CTE와 달리, 재귀적으로 데이터를 생성해가는 CTE이다. 

이와 관련된 내용은 별도의 글로 따로 작성해두었다! 

https://yeonnys.tistory.com/entry/MySQL-Recursive-CTE

 

[MySQL] Recursive CTE

코딩테스트 문제를 연습하다가 기존 테이블을 활용하지 않는 새로운 테이블을 만들어야하는 문제에 닥쳤다. 이를 해결하기 위해 찾아보다가 Recursive CTE라는 새로운 문법을 알게 되었다. https://

yeonnys.tistory.com

 

즉, Recursive CTE를 활용해 0부터 23까지 숫자를 나타내는 별도의 테이블을 생성하고, 

이를 본래 테이블과 JOIN하여 입양 건 수를 세는 것이다. 

 

 

앞서 말한 Recursive CTE를 실행하면, 위와 같은 결과가 나오게 된다. 

이를 HOUR(DATETIME)과 JOIN하며, 이 때 JOIN 조건은 CTE 테이블의 모든 값이 들어갈 수 있도록 한다

 

다른 풀이

SET을 사용한 풀이도 볼 수 있었다. 

SET은 어떤 변수에 특정 값을 할당할 때 쓰는 명령어이다. 

SET @HOUR = -1;
SELECT (@HOUR := @HOUR +1) AS HOUR
FROM ANIMAL_OUTS
WHERE @HOUR < 23;

 

즉, 위와 같은 쿼리는 @HOUR 변수에 -1을 할당한 후 22까지 +1씩 더해준다는 의미이다. 

최종적으로 이를 이용해 입양 건 수를 다음과 같이 셀 수 있다. 

 

SET @HOUR = -1;
SELECT (@HOUR := @HOUR +1) AS HOUR,
    (SELECT COUNT(HOUR(DATETIME)) 
    FROM ANIMAL_OUTS 
    WHERE HOUR(DATETIME)=@HOUR) AS COUNT 
    FROM ANIMAL_OUTS
WHERE @HOUR < 23;

 

이 때 주의할 점은, 

SET 이외의 명령문에서는 "="이 비교연산자로 취급되기 때문에

SELECT 문에서 이를 활용할 때는 ":="을 사용해야 한다는 것이다. 

 

느낀점

생각보다 어려운 문제여서 처음 아는 것이 많았던 문제였다. 

잘 기억해두고, 다음에 다시 풀어봐야겠다. 

 

728x90