소피it블로그

[SQL] 프로그래머스 SQL 고득점 Kit - GROUP BY (MySQL) 본문

CS/데이터베이스

[SQL] 프로그래머스 SQL 고득점 Kit - GROUP BY (MySQL)

sophie_l 2022. 11. 4. 00:35

https://school.programmers.co.kr/learn/courses/30/parts/17044

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

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

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

WHERE절을 

WHERE APNT_YMD LIKE '2022-05%'

라고 해주는 것이 더 깔끔할 것 같다.

 

GROUP BY를 잘 안 써봐서 헤맸다.

 

2. 식품분류별 가장 비싼 식품의 정보 조회하기

SELECT CATEGORY, PRICE MAX_PRICE, PRODUCT_NAME
FROM FOOD_PRODUCT
WHERE CATEGORY IN ('과자', '국', '김치', '식용유')
AND PRICE IN (SELECT MAX(PRICE)
              FROM FOOD_PRODUCT
             GROUP BY CATEGORY)
ORDER BY PRICE DESC

WHERE절에 SELECT절이 통으로 들어가는 게 낯설어서 헤맸다.

 

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

SELECT B.INGREDIENT_TYPE, SUM(A.TOTAL_ORDER) TOTAL_ORDER
FROM FIRST_HALF A
JOIN ICECREAM_INFO B
ON A.FLAVOR = B.FLAVOR
GROUP BY B.INGREDIENT_TYPE
ORDER BY A.TOTAL_ORDER

이 코드는 여러 번 더 들여다 봐야 할 듯

풀기는 했지만 SUM이 이해가 잘 가지 않는다.

 

테이블이 2개이기 때문에 가장 먼저 JOIN을 생각해봤고, 통했다.

 

4. 즐겨찾기가 가장 많은 식당 정보 출력하기

SELECT FOOD_TYPE, REST_ID, REST_NAME, FAVORITES
FROM REST_INFO
WHERE (FOOD_TYPE, FAVORITES) IN (SELECT FOOD_TYPE, MAX(FAVORITES)
                              FROM REST_INFO
                              GROUP BY FOOD_TYPE)
ORDER BY FOOD_TYPE DESC

WHERE절에 SELECT절이 포함되는 부분이 어려웠다.

 

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

-- WHERE절에 조건 명시
SELECT ANIMAL_TYPE, COUNT(ANIMAL_ID) 'count'
FROM ANIMAL_INS
WHERE ANIMAL_TYPE IN ('Cat', 'Dog')
GROUP BY ANIMAL_TYPE
ORDER BY ANIMAL_TYPE

-- HAVING절에 조건 명시(예전에 썼던 코드)
SELECT ANIMAL_TYPE, COUNT(*) AS COUNT
FROM ANIMAL_INS
GROUP BY ANIMAL_TYPE
HAVING ANIMAL_TYPE IN ('Cat', 'Dog')
ORDER BY ANIMAL_TYPE

두 코드 다 통과한다.

 

6. 동명 동물 수 찾기

-- 조건 전부 HAVING절에
SELECT NAME, COUNT(NAME) COUNT
FROM ANIMAL_INS
GROUP BY NAME
HAVING COUNT(NAME) >= 2 AND NAME IS NOT NULL
ORDER BY NAME

-- 조건 일부 WHERE절에 (예전에 작성한 코드)
SELECT NAME, COUNT(*) AS COUNT
FROM ANIMAL_INS
WHERE NAME IS NOT NULL
GROUP BY NAME
HAVING COUNT > 1
ORDER BY NAME

COUNT와 같은 집계함수의 경우 조건문에 들어갈 때 WHERE절이 아닌 HAVING 절에 들어가야 한다.

한편 집계함수가 아닌 경우 WHERE에 들어가든 HAVING에 들어가든 상관 없는지는 확실히 모르겠다. 이 문제에선 무관한듯.

 

7. 입양 시각 구하기(1)

SELECT HOUR(DATETIME) HOUR, COUNT(*) COUNT
FROM ANIMAL_OUTS
WHERE HOUR(DATETIME) BETWEEN 09 AND 20
GROUP BY HOUR(DATETIME)
ORDER BY HOUR(DATETIME)

-- DATETIME만 다르게 표현한 코드 (예전에 작성)
SELECT HOUR(DATETIME), COUNT(*) AS COUNT
FROM ANIMAL_OUTS
WHERE HOUR(DATETIME) >= 9 AND HOUR(DATETIME) < 20
GROUP BY HOUR(DATETIME)
ORDER BY HOUR(DATETIME)

DATETIME을 두 가지 방식으로 표현할 수 있었다.

그런데 BETWEEN의 경우 끝부분 경계값 포함인지 아닌지는 찾아봐야 할듯

 

8. 년, 월, 성별 별 상품 구매 회원 수 구하기

SELECT YEAR(B.SALES_DATE) YEAR, MONTH(B.SALES_DATE) MONTH, A.GENDER, COUNT(DISTINCT A.USER_ID) USERS
FROM USER_INFO A
JOIN ONLINE_SALE B
ON A.USER_ID = B.USER_ID
WHERE A.GENDER IS NOT NULL
GROUP BY YEAR, MONTH, GENDER
ORDER BY YEAR, MONTH, GENDER

JOIN - ON, WHERE, DISTINCT 등 전체적으로 많이 헤맸다. 꼼꼼히 다시 풀어봐야 할듯.

 

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

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
ORDER BY HOUR

굉장히 어려웠다.

SET @HOUR := -1;

로 변수 선언해준 후 1씩 더해가는 방식이 처음 작성해보는 방식인지라 다른 분들의 코드를 많이 참조해야 했다.

아직도 =와 :=의 차이를 잘 모르겠고

SELECT 안에 또 다른 SELECT절이 들어가는 것도 어렵고

변수 선언 후 세미콜론을 안 적어주니 오류가 났다. 왜인지는 모르지만 필수로 적어줘야 하나보다.

 

10. 가격대 별 상품 개수 구하기

SELECT TRUNCATE(PRICE, -4) PRICE_GROUP, COUNT(PRODUCT_ID) PRODUCTS
FROM PRODUCT
GROUP BY PRICE_GROUP
ORDER BY PRICE_GROUP

TRUNCATE(PRICE, -4)라는 메서드를 처음 보았다. PRICE를 뒤에서부터 4개 버리라는 뜻이라고 한다.

또한 GROUP BY와 ORDER BY에 alias(라고 하나? 용어를 모르겠다)를 사용할 수도 있다는 것을 처음 알았다.