[프로그래머스] SQL 고득점 키트 풀이 및 정리 - 2편 GROUP BY

Bini by Bini·2023년 4월 5일
0

코테

목록 보기
21/24

2편 - GROUP BY

[출제 빈도 : 보통, 평균 점수 : 보통, 문제세트 : 16]

문제는 풀이한 사람이 많은 순서로 풀이하겠다.

✨ 고양이와 개는 몇 마리 있을까

[Level 2]

답안

SELECT ANIMAL_TYPE, COUNT(ANIMAL_TYPE) AS count
FROM ANIMAL_INS
GROUP BY ANIMAL_TYPE
ORDER BY ANIMAL_TYPE

ANIMAL_TYPE이 같은 것들끼리 GROUP으로 묶는다.
그룹화 후 COUNT(ANIMAL_TYPE)을 하면, 그룹화 된 것들 각각의 개수를 구할 수 있다.


✨ 동명 동물 수 찾기

[Level 2]

조건
1. NAME이 두번 이상 쓰였는가
2. NAME이 NULL인 동물 제외

+결과 이름 순 오름차순 정렬

답안

SELECT NAME, COUNT(NAME) AS COUNT
FROM ANIMAL_INS
WHERE NAME IS NOT NULL
GROUP BY NAME
HAVING COUNT(*) >= 2
ORDER BY NAME
SELECT NAME, COUNT(NAME)
FROM ANIMAL_INS
GROUP BY NAME
HAVING COUNT(NAME) >= 2
ORDER BY NAME

두가지 모두 답이 될 수 있다.

COUNT(*) VS COUNT(컬럼명) : NULL 처리 유무

  1. NAME이 두번 이상 쓰였는지 확인하기 위해 GROUP BY NAME : NAME기준 그룹화
  2. HAVING에서 NAME이 2번 이상 쓰였는지 확인
    여기서 두 코드가 차이를 보인다.
    1️⃣ 첫번째 코드는 COUNT(*)을 해주었다. 이 경우 NULL인 값 또한 집계하므로 WHERE 구문에서 NULL이 아닌 조건을 추가해야 한다.
    2️⃣ 두번째 코드는 COUNT(NAME)을 해주었다. COUNT 안에 컬럼명을 넣는 경우 NULL이 아닌 값만 집계하므로 NULL을 따로 처리할 필요가 없다.
  3. NAME과 NAME을 COUNT한 값인 COUNT(NAME)을 SELECT

✨ 입양 시각 구하기(1)

[Level 2]

답안

SELECT HOUR(DATETIME) AS HOUR, COUNT(*) AS COUNT
FROM ANIMAL_OUTS
GROUP BY HOUR(DATETIME)
HAVING HOUR BETWEEN 9 AND 19
ORDER BY HOUR(DATETIME)

HAVING구문에는 순수 컬럼만

위의 코드에서 HAVING HOUR(DATETIME) BETWEEN 9 AND 19으로 하면

SQL 실행 중 오류가 발생하였습니다.
Unknown column ‘datetime’ in ‘having clause’

이런 오류가 발생한다.

HAVING 이후 조건을 거는 컬럼은, 위와 같이 HOUR만을 뽑아주는 COMMAND가 가미된 컬럼이 아닌, 순수 컬럼인 HOUR 이런 식으로 작성해야 한다.

그 전에! HOUR(DATETIME)에 새로운 컬럼명을 alias로 붙여줘야 한다. 나는 HOUR로 붙였다.


✨ 입양 시각 구하기(2) 🔥

[Level 4]

뭐야 ~ 개쉽네 하며 GROUP BY로 풀었는데 틀리고 읭 저걸 어케하지 null 처리로 해야되나 ..했는데
null값 처리도 아니고, 아예 데이터 자체가 없는 것을 만들어내는 거여서 바로 구글링.

답안

SET @HOUR = -1;
SELECT (@HOUR := @HOUR + 1) AS HOUR,
    (SELECT COUNT(*)
     FROM ANIMAL_OUTS
     WHERE HOUR(DATETIME) = @HOUR) AS COUNT
FROM ANIMAL_OUTS
WHERE @HOUR < 23

SET 함수 : 변수 선언, :=

쿼리문에서 로컬 변수를 사용하기 위해 SET 함수에서 변수를 선언한다.

  • SET 옆에 변수명과 초기값을 설정한다.
    - @가 붙은 변수는 프로시저가 종료되어도 유지된다.
    • 이를 통해 값을 누적하여 0부터 23까지 값을 표현할 수 있다.
  • := 과 = 혼동 주의. 첫줄에는 SET @HOUR := -1, SET @HOUR = -1 모두 가능하다.
    그러나 SELECT 안에서는 := 로 값을 대입해주어야 한다.
    (SET 이외의 명령문에서는 = 가 비교연산자로 취급되기 때문이다.)
  • SELECT (@HOUR := @HOUR + 1) 을 통해 @HOUR 값이 1씩 증가하며 SELECT문 전체를 실행한다.
  • @HOUR이 22일 때도 조건에 걸리지 않으므로 23까지 쿼리를 진행, 23이 되면 WHERE 조건에 걸리므로 멈춘다.

✨ 성분으로 구분한 아이스크림 총 주문량

조건

  • 총주문량을 오름차순으로 정렬
  • 총주문량 나타내는 컬럼명은 TOTAL_ORDER로 지정

답안

SELECT I.INGREDIENT_TYPE, SUM(F.TOTAL_ORDER) AS TOTAL_ORDER
FROM FIRST_HALF AS F
    LEFT JOIN ICECREAM_INFO AS I
    ON F.FLAVOR = I.FLAVOR
GROUP BY I.INGREDIENT_TYPE
ORDER BY TOTAL_ORDER
SELECT I.INGREDIENT_TYPE, SUM(F.TOTAL_ORDER) AS TOTAL_ORDER
FROM FIRST_HALF AS F
    LEFT JOIN ICECREAM_INFO AS I
    ON F.FLAVOR = I.FLAVOR
GROUP BY I.INGREDIENT_TYPE
ORDER BY TOTAL_ORDER

두 쿼리 모두 같은 결과를 얻는다.


✨ 진료과별 총 예약 횟수 출력하기

SELECT MCDP_CD AS '진료과코드', COUNT(MCDP_CD) AS '5월예약건수'
FROM APPOINTMENT
WHERE YEAR(APNT_YMD) = 2022
    AND MONTH(APNT_YMD) = 05
GROUP BY MCDP_CD
ORDER BY COUNT(MCDP_CD), MCDP_CD

WHERE YEAR(APNT_YMD) = 2022 AND MONTH(APNT_YMD) = 05 로 해도 되고
WHERE APNT_YMD LIKE '2022-05%'로 해도 된다.

🚗 ORDER BY 안에 기준으로 COUNT(MCDP_CD)가 들어간다.
(처음에 alias 했으니까 '5월예약건수'로 해도 되지 않을까 했으나 어림없었다.)

GROUP BY COUNT

그룹으로 묶은 후 집계.

  1. NAME 칼럼을 기준으로 그룹별로 COUNT
SELECT NAME, COUNT(NAME) AS COUNT
FROM TABLE
GROUP BY NAME
  1. NAME 칼럼을 기준으로 총 COUNT
SELECT COUNT(NAME) AS COUNT
FROM (
		SELECT NAME
        FROM TABLE
        GROUP BY NAME
) AS A 

위의 문제에서 진료과 코드의 개수를 구하려면

SELECT COUNT(MCDP_CD) AS CNT
FROM (
        SELECT MCDP_CD
        FROM APPOINTMENT
        GROUP BY MCDP_CD
) AS A

이렇게 해주면 된다. 그리고 끝에 alias를 꼭 해줘야 한다. (왜인지는 모르겠다. 코테 끝나고 연구해봐야지(아마도))


JOIN 편 먼저 풀고 시간이 되면 GROUP BY를 더 풀이하겠다!

profile
My Precious Records

0개의 댓글