강의로 돌아가기
leo kim

[mysql] 정답공유와 문제해설 (recursive, with문 활용)

문제 쪼개 보기

보호소에서는 몇 시에 입양이 가장 활발하게 일어나는지 알아보려 합니다. 0시부터 23시까지, 각 시간대별로 입양이 몇 건이나 발생했는지 조회하는 SQL문을 작성해주세요. 이때 결과는 시간대 순으로 정렬해야 합니다.

  • 시간대별로 : ~~별로 라는 워딩이 사용된 경우, group by를 활용하면 쉽게 문제를 해결할 수 있습니다.
  • 입양이 몇건이나 : 입양을 어떻게 카운팅할 수 있을까요? ANIMAL_ID를 활용합니다.
  • 0시부터 23시까지 : 다만 주어진 테이블을 group by를 활용해서 시간대별로 살펴보면 0시~6시, 20시~23시는 출력되지 않습니다. 이는 기존 데이터에 해당 시간대에 입양이 일어난 로그가 없기 때문입니다.
    • 이 문제를 해결하기 위해, 0시~23시를 커버하는 테이블이 필요합니다.
    • 이를 위해 WITH문과 RECURSIVE를 활용하여 임시 테이블을 생성할 수 있습니다. (RECURSIVE는 비교적 최근 문법으로 구글링 참조)
  • 결과는 시간대 순으로 정렬해야 : 정렬 조건은 시간이 기준입니다. 정렬은 ORDER BY를 활용합니다.

추가 해설

  • HOUR()의 경우 DATETIME에서 시간만 추출합니다. 유사하게 연,월,일을 구하고 싶다면, YEAR() MONTH() DAY()도 가능합니다.
  • DISTINCT의 경우 중복값을 제거합니다. DISTINCT ANIMAL_ID는 COUNT()문으로 감싸 고유값을 카운팅할 수 있습니다. 문제에는 중복값이 없었지만, 실무를 가정하여 중복값 제거를 포함하였습니다.
  • WITH문과 사용된 RECURSIVE의 경우 mysql 5.7버전이하에선 지원되지 않습니다. 때문에 다른 코딩 테스트 플랫폼에선 사용이 불가할 수 있습니다.

아래가 직접 작성해본 정답입니다.
더 좋은 방법이나 코드 가독성에 대한 피드백 환영입니다.
도움이 되셨다면 댓글 남겨주세요.

작성중인 코드―solution.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
WITH RECURSIVE tb1 AS (
    SELECT 0 AS HOUR
    UNION ALL
    SELECT HOUR+1 FROM tb1 WHERE HOUR < 23
) , tb2 AS (
    SELECT HOUR(DATETIME) AS HOUR
         , COUNT(DISTINCT ANIMAL_ID) AS CNT
    FROM ANIMAL_OUTS
    GROUP BY HOUR
)

SELECT tb1.HOUR
     , CASE WHEN tb2.CNT IS NULL THEN 0 ELSE CNT END AS CNT
FROM tb1
    LEFT JOIN tb2 ON tb1.HOUR = tb2.HOUR
ORDER BY HOUR
  • data2better

    친절한 풀이 감사합니다.

    data2better―2023.01.29 22:33
  • catveloper365

    친절한 풀이 감사합니다. 그런데 ANIMAL_ID는 PK이기 때문에 중복값이 존재할 수없어 굳이 DISTINCT를 할 필요는 없을것같습니다

    catveloper365―2023.03.21 02:42
2 개의 답변
ParkHaRyul

좋은 해설글 감사합니다.

Journey

감사합니다!

답변 쓰기
이 입력폼은 마크다운 문법을 지원합니다. 마크다운 가이드 를 참고하세요.