SQL 고득점 Kit - (3) GROUP BY

프로그래머스 SQL 고득점 Kit 문제풀이 3편 (GROUP BY 편)

문제설명

ANIMAL_INS 테이블은 동물 보호소에 들어온 동물의 정보를 담은 테이블입니다. ANIMAL_INS 테이블 구조는 다음과 같으며, ANIMAL_ID, ANIMAL_TYPE, DATETIME, INTAKE_CONDITION, NAME, SEX_UPON_INTAKE는 각각 동물의 아이디, 생물 종, 보호 시작일, 보호 시작 시 상태, 이름, 성별 및 중성화 여부를 나타냅니다.

NAMETYPENULLABLE
ANIMAL_IDVARCHAR(N)FALSE
ANIMAL_TYPEVARCHAR(N)FALSE
DATETIMEDATETIMEFALSE
INTAKE_CONDITIONVARCHAR(N)FALSE
NAMEVARCHAR(N)TRUE
SEX_UPON_INTAKEVARCHAR(N)FALSE



1. 고양이와 개는 몇 마리 있을까? (LEVEL 2)

동물 보호소에 들어온 동물 중 고양이와 개가 각각 몇 마리인지 조회하는 SQL문을 작성해주세요. 이때 고양이를 개보다 먼저 조회해주세요.

풀이

SELECT ANIMAL_TYPE, COUNT(*) FROM ANIMAL_INS
WHERE ANIMAL_TYPE IN ('Cat','Dog')
GROUP BY ANIMAL_TYPE  
ORDER BY ANIMAL_TYPE
  • GROUP BY 문은 지정된 열을 기준으로 데이터들을 그룹화해주는 함수이다.
  • 동물 보호소에 고양이와 개 이외의 다른 동물이 있을 수 있으므로 WHERE를 통해 고양이와 개만을 조건으로 지정해주고, 그룹화하고, 고양이부터 나오도록 ORDER BY문을 통해 정렬해주면 된다.



2. 동명 동물 수 찾기 (LEVEL 2)

동물 보호소에 들어온 동물 이름 중 두 번 이상 쓰인 이름과 해당 이름이 쓰인 횟수를 조회하는 SQL문을 작성해주세요. 이때 결과는 이름이 없는 동물은 집계에서 제외하며, 결과는 이름 순으로 조회해주세요.

풀이

SELECT NAME, COUNT(*) FROM ANIMAL_INS
GROUP BY NAME HAVING COUNT(NAME) >=2
ORDER BY NAME
  • GROUP BY 에서 HAVING을 사용하면 그룹화 결과 출력될 조건을 지정해 줄 수 있다. HAVING 과 WHERE의 차이는 HAVING은 조건 필터링을 그룹화를 하고난 후에 진행하고, WHERE는 조건 필터링을 그룹화 전에 한다.
  • 지금의 경우와 같이 그룹화를 하고 그 결과가 2개이상인 대상을 출력하는 문제에서는 HAVING을 활용하는 것이 맞다.



3. 입양 시각 구하기(1) (LEVEL 2)

ANIMAL_OUTS 테이블은 동물 보호소에서 입양 보낸 동물의 정보를 담은 테이블입니다. ANIMAL_OUTS 테이블 구조는 다음과 같으며, ANIMAL_ID, ANIMAL_TYPE, DATETIME, NAME, SEX_UPON_OUTCOME는 각각 동물의 아이디, 생물 종, 입양일, 이름, 성별 및 중성화 여부를 나타냅니다.

NAMETYPENULLABLE
ANIMAL_IDVARCHAR(N)FALSE
ANIMAL_TYPEVARCHAR(N)FALSE
DATETIMEDATETIMEFALSE
NAMEVARCHAR(N)TRUE
SEX_UPON_OUTCOMEVARCHAR(N)FALSE

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

풀이

SELECT HOUR(DATETIME) AS HOUR , COUNT(*) AS COUNT FROM ANIMAL_OUTS
GROUP BY HOUR HAVING  HOUR BETWEEN 9 AND 19
ORDER BY HOUR
  • HOUR 함수를 이용해, DATETIME 열에서 시간 정보만을 추출한 후 HOUR 라는 이름으로 선언을 했다.
  • 그 이후 HOUR를 기준으로 그룹화를 시킨다. HAVING절의 조건문을 통해 9~19사이의 데이터만을 추출하도록 조건을 지정해 주었다.
  • BETWEEN A AND B 를 사용해 A~B 사이의 조건을 지정해 줄 수 있다.



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

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


HOURCOUNT
00
10
20
30
40
50
60
73
81
91
102
1113
1210
1314
149
157
1610
1712
1816
192
200
210
220
230

풀이

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

SELECT TEMP.HOUR, COUNT(HOUR(ANIMAL_OUTS.DATETIME)) AS COUNT
FROM TEMP LEFT JOIN ANIMAL_OUTS
ON TEMP.HOUR = HOUR(ANIMAL_OUTS.DATETIME)
GROUP BY TEMP.HOUR
ORDER BY TEMP.HOUR ;
  • 데이터가 20시 이후부터는 존재하지 않지만, 23시 데이터까지 출력해야하기 때문에 임시 테이블을 생성하고 LEFT JOIN을 통해 병합하는 방법을 이용했다.
  • WITH RECURSIVE 를 이용해 재귀쿼리를 이용한 가상의 테이블을 만들 수 있다. 초기값이 0인 HOUR에 1씩 더해서 WHERE절을 만족하는 23까지 반복한다.
  • 그러므로 TEMP라는 테이블에는 0~23까지의 숫자가 담겨있다.
  • JOIN(교집합) 후에 출력학 형태를 SELECT를 통해 지정해준다. 여러개의 테이블이 사용되는 연산의 경우 열앞에 원래 테이블을 써주어야 한다.
  • TEMP와 ANIMAL_OUTS를 LEFT JOIN 시켜준다. LEFT JOIN 은 왼쪽에 존재하는(처음 언급한) 테이블을 기준으로 ON 뒤에 나와있는 조건에 맞게 병합시키는 함수이다.
  • LEFT JOIN은 왼쪽에 나와있는 테이블은 전부 다 출력되고 그에 맞게 오른쪽 테이블을 병합시킨다고 생각하면 편하다.

좋은 웹페이지 즐겨찾기