세조목

SQL 예제 정리('입양 시각 구하기(2)')(24.05.08) 본문

데이터 분석 공부/SQL

SQL 예제 정리('입양 시각 구하기(2)')(24.05.08)

세조목 2024. 5. 8. 20:21

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

 

프로그래머스

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

programmers.co.kr

0시부터 23시까지, 각 시간대별로 입양이 몇 건 발생했는지를 조회하는 것이 이번 예제의 요구사항입니다.

간단한 요구사항인데 ANIMAL_OUTS 테이블에 포함된 시간을 확인해보니

7시부터 19시까지밖에 없습니다.

문제에서는 0시부터 23시까지라고 했으니 0~6시, 20~23시 데이터를 구해야합니다.

어떻게 구할 수 있을까요?

 

다양한 방법이 있을 수 있겠지만 저는 재귀함수를 썼습니다.

'재귀'자신에게로 다시 돌아온다는 의미입니다.

마치 부메랑처럼 말이죠.

WITH RECURSIVE NEW_TIME AS (
    SELECT 0 T
    
    UNION ALL
    
    SELECT T+1
    FROM NEW_TIME
    WHERE T<23
)

위 쿼리를 보시면 'RECURSIVE NEW_TIME AS'라는 부분이 보이실텐데요,

'NEW_TIME'은 이름붙이고 싶은대로 붙이는거라서 상관이 없는데 중요한건 WITH RECURSIVE를 적어주는 겁니다.

이렇게 적어준 후 소괄호 안에 어떤식으로 재귀할 지에 대한 쿼리문을 작성해주면 됩니다.

 

1. 우선 SELECT 0 T는 NEW_TIME이라는 가상의 테이블에 0을 넣어주는 쿼리입니다.

2. 다음으로 FROM NEW_TIME으로 넘어갑니다.

    NEW_TIME 테이블의 T라는 컬럼에는 0이 들어있습니다.

3. WHERE T < 23에 해당되니 SELECT절로 올라갑니다.

    T컬럼에 1을 더해줍니다.

 

이 프로세스를 T<23에 해당할 때까지 반복합니다.

그럼 T컬럼에는 0부터 23까지가 저장될겁니다.

마치 Python의 for문과 비슷하죠?

 

이제 이렇게 완성된 NEW_TIME 테이블과 ANIMAL_OUTS 테이블을 JOIN시켜줍니다.

WITH RECURSIVE NEW_TIME AS (
    SELECT 0 T
    
    UNION ALL
    
    SELECT T+1
    FROM NEW_TIME
    WHERE T<23
)
SELECT NT.T HOUR,
       COUNT(DISTINCT AO.ANIMAL_ID) COUNT
FROM NEW_TIME NT LEFT JOIN ANIMAL_OUTS AO ON NT.T=HOUR(AO.DATETIME)
GROUP BY HOUR
ORDER BY HOUR;

NEW_TIME 테이블에 0부터 23까지의 값이 들어있으니

NEW_TIME 테이블을 좌측에 둘 경우 LEFT JOIN을, 우측에 둘 경우 RIGHT JOIN을 해줘야합니다.

그런 다음 SELECT절에 HOUR와 고유한 ANIMAL_ID의 개수를 COUNTING한 COUNT 컬럼을 넣어주면

아래와 같은 결과를 확인할 수 있습니다.