호기심 많은 분석가

[MySQL] 프로그래머스 Coding_Test / GROUP BY (2) 본문

Coding/Coding Test & Algorithm

[MySQL] 프로그래머스 Coding_Test / GROUP BY (2)

DA Hun 2021. 5. 6. 20:29

포스팅 개요

 SQL 문법과 익숙해지고자 프로그래머스의 SQL Coding Test 문제들을 풀어봄. 그중 GROUP BY 파트의 문제들을 기록해두었습니다. 앞선 문제는 2021.05.06 - [Coding Test & Algorithm] - [SQL] 프로그래머스 Coding_Test / GROUP BY (1) 확인하실 수 있습니다


포스팅 본문

 아래의 문제들은 모두 동일한 TABLE을 기준으로 문제가 주어졌습니다.

TABLE 설명

TABLE

 


4. 입양 시각 구하기 (2)

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

입양 시각 구하기 (2)

WITH RECURSIVE TEMP AS (
SELECT 0 AS HOUR
UNION ALL
SELECT HOUR+1 FROM TEMP WHERE HOUR<23
)

SELECT HOUR, IFNULL(CNT, 0) AS COUNT FROM TEMP
LEFT OUTER JOIN
(SELECT HOUR(DATETIME) AS HR, COUNT(DATETIME) AS CNT
FROM ANIMAL_OUTS 
GROUP BY HR) AS ORI
ON TEMP.HOUR = ORI.HR
ORDER BY TEMP.HOUR

 이 문제는 코드에 앞서 WITH RECURSIVE 문법에 대해 짚고 넘어가겠습니다.

WITH RECURSIVE(재귀) 쿼리 계층 구조라 불리고, 

  1. 메모리 상에 가상의 테이블을 저장하여
  2. 재귀 쿼리를 이용하여 실제로 테이블을 생성하거나 데이터 삽입(INSERT)을 하지 않고 가상 테이블을 생성

하여 사용합니다. 문법은 아래와 같습니다.

WITH RECURSIVE 테이블명 AS (
SELECT 초기값 AS 컬럼 별명1
UNION ALL
SELECT 컬럼 별명1 계산식 FROM 테이블명 WHERE 제어문)

 문제를 해결하기 위해 이 WITH RECURSIVE 문법을 통해 아래와 같은 TEMP라는 TABLE을 생성해줍니다.

 이제 우리는 0시부터 23시까지의 행을 가진 TABLE을 가지고 있습니다. 그 테이블과 우리가 원하는 데이터를 가진 아래의 테이블을 결합해보겠습니다.

 JOIN 문법 중 LEFT OUTER JOIN을 사용해서 TEMP 테이블의 HOUR COLUMN에 기준하여 두 번째 데이블의 HR COLUMN을 JOIN 시켜줍니다. 그다음 정답에 필요한 HOUR과 CNT COLUMN을 추출하여 줍니다. LEFT OUTER JOIN 이기 때문에 CNT 값이 존재하지 않는 경우 NULL 값이 입력됩니다. 이때 IFNULL() 함수를 사용해줍니다.

 IFNULL(exp1, exp2)의 함수는 exp1이 NULL일 경우 exp2 값을, NULL이 아닐 경우 exp1을 반환하여줍니다.

 

 그 결과 문제가 원하는 형태의 테이블을 뽑아낼 수 있습니다.


 LEVEL 4 답게 꽤 어려운 문제였습니다. 이 문제 덕분에 WITH RECURSIVE 문법과 LEFT OUTER JOIN 문법을 익혀볼 수 있었습니다. 이 문제로 어려움을 겪은 어느 분에게 도움이 되는 포스팅이었기를 바랍니다. 다음 IS NULL파트에서 뵙겠습니다. :)