본문 바로가기

SQL - Mysql & Oracle/SQL 실전 코딩 테스트

[Oracle] 입양 시각 구하기(1) - Group by 사용법 마스터하기

반응형

이번 포스팅에서는 Oracle 언어를 사용하여 프로그래머스 고득점 키트 문제 중 "입양 시각 구하기(1)" 문제를 풀어볼 것이다. 단순 정답만 제공하는 것이 아니라 Group by 문법을 정확하게 사용하는 방법까지 알아보면서 실력을 키워보는 것이 목표이다. 

 

문제의 출처 및 기본 해설

 

문제의 출처는 당연히 프로그래머스 SQL 고득점 키트 중에서 Group by 영역을 찾아가면 된다. 이 문제의 소스 데이터는 Kaggle의 동물 입양 데이터를 기반으로 기출 문제가 만들어졌기 때문에 더 심도 있는 공부를 원하는 사람들은 사이트를 참고해도 좋을 것이다. 참고로구글에 Austin Animal Center Shelter Intakes and Outcomes 라고 검색하면 원하는 데이터를 바로 찾을 수 있다. 

 

 

 

 

문제의 요구사항 및 데이터 파악하기

 

  • 문제의 요구사항의 핵심은 두 가지로 요약할 수 있다. 
    • 요구사항 1. 9부터 19까지 시간대별로 입양이 몇 건이나 발생했는지 조회하는 결과
    • 요구사항 2. 노출 결과는 시간 순서대로 나열하는 것

 

  • 기초 데이터 구조 파악하기

입양시각구하기(2)의 데이터 구조

 

여기서 활용해야하는 것은 명확하게 두 가지 Column있다. 첫 번째는 집계의 기준이 되는 animal id가 있고, 이후 이것을 고유한 수로 나타내야 한다. 두 번째는 입양 시간을 나타내는 datetime이다. 하지만 여기는 시간이 아닌 yyyy-mm-dd hh:mm:ss의 구조로 되어 있기 때문에 정제가 필요한 상황이다.  

 

 

 

Orcale - Group by와 Where절을 통한 코드 문제 풀이

 

  • 첫 번째. 프로그래머스 입양시각 구하기(1) 코드 해설 - group by 와 where
1
2
3
4
5
6
7
8
9
10
11
12
13
with base_data as (
    SELECT EXTRACT(HOUR FROM CAST( datetime  AS TIMESTAMP) ) as HOUR
        , animal_id
    FROM ANIMAL_OUTS 
)
 
SELECT t1.HOUR
    , count(distinct t1.animal_id) as COUNT
FROM BASE_DATA t1
WHERE 1 = 1
    and t1.HOUR between 9 and 19
GROUP BY t1.HOUR
ORDER BY 1 ASC
cs

 

우선 base_data 영역에서 1차적인 데이터 정제를 실시하였다. 정제의 목적은 시간 데이터에서 우리가 필요한 HOUR 데이터만 추출하는 것과 필요 없는 Column들을 제거해주는 것이다. 

 

Group by의 가장 중요한 것은 집계의 기준과 집계의 대상을 선정하는 것이다. 문제의 요구사항1번에 따라 집계의 기준이되는 것은 입양 시간인 HOUR이기 때문에 "group by t1.hour"을 통해서 명령어를 수행한 것이다. 

 

집계의 대상은 입양된 동물의 수를 고유하게 세야 하기 때문에 animal_id가 되어야 한다. 이때 각 문제마다 적합한 집계함수를 써야 한다. 우리는 "중복이 없는 동물의 수"를 세야 하기 때문에 COUNT와 DISTINCT 조건을 동시에 걸어주었다. 

 

문제의 요구사항2번에서는 입양시간을 9 ~ 19시로 제한을 했고, 이를 시간 순서대로 나열할 것을 요구하였다. 따라서 Where 절에서 시간에 대한 제한을 두었고, Order by 에서는 정렬 순서를 지정하였다. 참고로 1이라는 숫자는 SELECT문에서 첫 번째 Column을 지칭한다. 

 

 

 

 

Orcale - Group by와 Where절을 통한 코드 문제 풀이

 

  • 두 번째. 프로그래머스 입양시각 구하기(1) 코드 해설 - group by 와 HAVING
1
2
3
4
5
6
7
8
9
10
11
with base_data as (
    SELECT EXTRACT(HOUR FROM CAST( datetime  AS TIMESTAMP) ) as HOUR
        , animal_id
    FROM ANIMAL_OUTS 
)
 
SELECT t1.HOUR
    , count(distinct t1.animal_id) as COUNT
FROM BASE_DATA t1
GROUP BY t1.HOUR HAVING t1.HOUR between 9 and 19
ORDER BY 1 ASC
cs

 

기타 조건은 동어반복이기 때문에 피하고, Group by의 고급 사용법인 HAVING절을 사용하는 것에 대해 안내하고자 한다. 집계가 되는 범위를 GROUP BY 절에서 동시에 지정할 수 있는데, HAVING이 바로 그 역할을 하는 것이다. 코드를 풀어서 설명하면, "나는 집계(GROUP BY)를 할 예정인데, 특정 범위(HAVING)에 있는 애들만 대상으로만 해줬으면 좋겠어"라고 SQL 문에서 말하는 것이다. 따라서 HAVING 뒤에 데이터 조건을 설명한다고 이해하면 완벽하게 SQL에서 집계문을 이해할 수 있는 것이다. 

 

 

반응형