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는 각각 동물의 아이디, 생물 종, 보호 시작일, 보호 시작 시 상태, 이름, 성별 및 중성화 여부를 나타냅니다.
NAME | TYPE | NULLABLE |
---|---|---|
ANIMAL_ID | VARCHAR(N) | FALSE |
ANIMAL_TYPE | VARCHAR(N) | FALSE |
DATETIME | DATETIME | FALSE |
INTAKE_CONDITION | VARCHAR(N) | FALSE |
NAME | VARCHAR(N) | TRUE |
SEX_UPON_INTAKE | VARCHAR(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는 각각 동물의 아이디, 생물 종, 입양일, 이름, 성별 및 중성화 여부를 나타냅니다.
NAME | TYPE | NULLABLE |
---|---|---|
ANIMAL_ID | VARCHAR(N) | FALSE |
ANIMAL_TYPE | VARCHAR(N) | FALSE |
DATETIME | DATETIME | FALSE |
NAME | VARCHAR(N) | TRUE |
SEX_UPON_OUTCOME | VARCHAR(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문을 실행하면 다음과 같이 나와야 합니다.
HOUR | COUNT |
---|---|
0 | 0 |
1 | 0 |
2 | 0 |
3 | 0 |
4 | 0 |
5 | 0 |
6 | 0 |
7 | 3 |
8 | 1 |
9 | 1 |
10 | 2 |
11 | 13 |
12 | 10 |
13 | 14 |
14 | 9 |
15 | 7 |
16 | 10 |
17 | 12 |
18 | 16 |
19 | 2 |
20 | 0 |
21 | 0 |
22 | 0 |
23 | 0 |
풀이
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은 왼쪽에 나와있는 테이블은 전부 다 출력되고 그에 맞게 오른쪽 테이블을 병합시킨다고 생각하면 편하다.
Author And Source
이 문제에 관하여(SQL 고득점 Kit - (3) GROUP BY), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@junhyeok-5/SQL-고득점-Kit-3-GROUP-BY저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)