[프로그래머스] SQL 정리 - GROUP BY (1)

유은선·2023년 5월 13일
0

Programmers_SQL

목록 보기
3/6
post-thumbnail

GROUP BY(1)

💎 가장 비싼 상품 구하기

MAX함수를 이용해 최댓값을 구해보자. 여기서 AS는 별칭을 의미한다.

SELECT MAX(PRICE) AS MAX_PRICE
FROM PRODUCT

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

고양이를 개보다 먼저 조회해야 하므로 ORDER BY도 사용해야한다.

SELECT ANIMAL_TYPE, COUNT(ANIMAL_TYPE)
FROM ANIMAL_INS
GROUP BY ANIMAL_TYPE
ORDER BY ANIMAL_TYPE;

🦝 동명 동물 수 찾기

GROUP BY와 함께 사용되는 HAVING 절을 사용하도록 한다.

SELECT NAME, COUNT(NAME) AS 'COUNT'
FROM ANIMAL_INS 
GROUP BY NAME
HAVING COUNT(NAME)>=2
ORDER BY NAME;

여기서 COUNT함수에 대해

  • COUNT(컬럼명)을 사용하면 NULL 값은 제외하고 COUNT
  • COUNT(*)를 사용하면 NULL도 포함하여 전부 COUNT

따라서, COUNT(*)을 작성했다면
WHERE NAME IS NOT NULL 을 함께 작성해야합니다.
(문제와는 관계없음)

🚗 자동차 종류 별 특정 옵션이 포함된 자동차 수 구하기

WHERE 컬럼명 LIKE "%단어%"를 사용하면 특정 컬럼에서 특정 단어가 들어간 행을 추출할 수 있고, 모두 XX시트 형태 이므로 '%시트%'를 사용하면 OPTIONS 컬럼 값에 '시트'가 하나 이상 포함된 행을 추출합니다.

SELECT CAR_TYPE, COUNT(OPTIONS) AS CARS
FROM CAR_RENTAL_COMPANY_CAR 
WHERE OPTIONS LIKE "%시트%"
GROUP BY CAR_TYPE
ORDER BY CAR_TYPE;

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

ORDER BY에도 COUNT를 써서 정렬이 가능하다.
또한 AS로 사용한 별칭을 ORDER BY에 써도 무방
ORDER BY 5월예약건수, 진료과코드;

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;

📁 카테고리 별 상품 개수 구하기

  • LEFT
    LEFT(컬럼명, 왼쪽부터 가져올 개수)
  • 상품 카테고리 코드별 상품 개수
    GROUP BYCOUNT를 사용해 상품 카테고리 코드별 상품개수 구해주기
SELECT LEFT(PRODUCT_CODE,2) AS CATEGORY,
COUNT(PRODUCT_ID) AS PRODUCTS
FROM PRODUCT 
GROUP BY CATEGORY
ORDER BY CATEGORY;

⏰ 입양 시각 구하기(1)

HAVING을 이용해 시간대별로 GROUP 마다 COUNT를 해준다
이때, HAVING 절에 HOUR(DATETIME)을 하지 않도록 주의(에러)

SELECT HOUR(DATETIME) AS HOUR, COUNT(DATETIME) AS COUNT
FROM ANIMAL_OUTS 
GROUP BY HOUR(DATETIME)
HAVING HOUR>=9 AND HOUR<=19
ORDER BY HOUR;

HAVING 절을 사용하지 않고 WHERE을 사용해도 코드를 작성할 수 있다.

SELECT HOUR(DATETIME) AS HOUR, COUNT(DATETIME) AS COUNT
FROM ANIMAL_OUTS 
WHERE HOUR(DATETIME)>=9 AND HOUR(DATETIME)<=19
GROUP BY HOUR(DATETIME)
ORDER BY HOUR;

🚙 자동차 평균 대여 기간 구하기

CAR_ID로 그룹을 묶고 HAVING으로 평균 대여 기간이 7일 이상인 컬럼을 출력
DATEDIFF(끝나는 날짜, 시작하는 날짜) 를 이용하는데, 차이에 1을 더해주는 것을 잊지말자🤣

SELECT CAR_ID, ROUND(AVG(DATEDIFF(END_DATE,START_DATE)+1),1) AS AVERAGE_DURATION
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY 
GROUP BY CAR_ID
HAVING AVG(DATEDIFF(END_DATE,START_DATE)+1) >= 7
ORDER BY AVERAGE_DURATION DESC, CAR_ID DESC;
  • ROUND
    ROUND(숫자, 출력하고 싶은 자릿수)
    ROUND(123.32, 1): 소수 둘째자리에서 반올림, 123.3
    ROUND(123.92): 소수 첫째자리에서 반올림, 124

👜 재구매가 일어난 상품과 회원 리스트 구하기

GROUP BY {컬럼1}, {컬럼2} 를 이용하면 두개의 컬럼에 대해서도 그룹화를 할 수 있습니다.
HAVING 절을 이용해 집계 결과에서 COUNT(*)가 2 이상인 데이터만을 조회

SELECT USER_ID, PRODUCT_ID
FROM ONLINE_SALE
GROUP BY USER_ID, PRODUCT_ID
HAVING COUNT(*) >=2
ORDER BY USER_ID, PRODUCT_ID DESC;

💰 가격대 별 상품 개수 구하기

  • TRUNCATE
    TRUNCATE(수, 자릿수): 수를 지정된 소수점 자리까지 버림하여 반환해주는 함수
  1. 자릿수를 명시하지 않았을 경우 기본값은 0이다. 즉, 정수로 반환
  2. 자릿수가 음수일 경우 지정된 정수부에서 버림
    EX) TRUNCATE(PRICE,-4) : 가격이 들어왔을때 뒤의 네자리수는 버려서 가격을 만원대로 출력
    EX) TRUNCATE(54.29,1) == 54.2
    EX) TRUNCATE(54.29,-1) == 50

TRUNCATE를 이용한 풀이1

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

TRUNCATE를 이용한 풀이2

가격(PRICE)를 10000로 나누고, 만자리 이하를 버려야한다.
자릿수를 명시하지 않으면 오류가 나므로 주의

  • FLOOR를 사용해도 비슷하게 풀이가 가능
SELECT TRUNCATE(PRICE/10000,0)*10000 AS PRICE_GROUP, COUNT(PRICE) AS PRODUCTS
FROM PRODUCT
GROUP BY PRICE_GROUP
ORDER BY PRICE_GROUP;

SELECT FLOOR(PRICE/10000)*10000 AS PRICE_GROUP, COUNT(PRICE) AS PRODUCTS
FROM PRODUCT
GROUP BY PRICE_GROUP
ORDER BY PRICE_GROUP;

CASE WHEN를 이용한 풀이

코드가 길어지지만 CASE WHEN을 사용해 그룹화하여 출력해도 된다.
CASE WHEN 0<=PRICE AND PRICE<=10000 THEN 0 을 써도 무방

SELECT 
CASE WHEN PRICE BETWEEN 0 AND 9999 THEN 0
WHEN PRICE BETWEEN 10000 AND 19999 THEN 10000
WHEN PRICE BETWEEN 20000 AND 29999 THEN 20000
WHEN PRICE BETWEEN 30000 AND 39999 THEN 30000
WHEN PRICE BETWEEN 40000 AND 49999 THEN 40000
WHEN PRICE BETWEEN 50000 AND 59999 THEN 50000
WHEN PRICE BETWEEN 60000 AND 69999 THEN 60000
WHEN PRICE BETWEEN 70000 AND 79999 THEN 70000
WHEN PRICE BETWEEN 80000 AND 89999 THEN 80000
ELSE 90000 END AS PRICE_GROUP,
COUNT(*) AS PRODUCTS
FROM PRODUCT
GROUP BY PRICE_GROUP
ORDER BY PRICE_GROUP;

🔎 상품 별 오프라인 매출 구하기

합계를 출력하라고 했으므로 SUM을 이용하고, GROUP BY를 이용해 같은 아이디별로 그룹을 만들어야 한다.

SELECT A.PRODUCT_CODE, SUM(B.SALES_AMOUNT*A.PRICE) AS SALES
FROM PRODUCT AS A 
JOIN OFFLINE_SALE AS B
ON A.PRODUCT_ID = B.PRODUCT_ID
GROUP BY A.PRODUCT_ID
ORDER BY SALES DESC, PRODUCT_CODE;

✨ 헤비 유저가 소유한 장소

서브쿼리를 이용해 작성

  • 주의할 점1: WHERE 문을 쓸 때, =을 쓰면 오류가 난다. 1개 이상의 행을 리턴하므로 IN을 써서 해결하면 된다!
  • 주의할 점2: 서브쿼리를 작성할 때, 마찬가지로 GROUP BY로 그룹들을 묶어준뒤, HAVING으로 그룹에 대한 조건을 달아주면 된다. 이 때 WHERE문을 쓰지 않도록 주의해주자😥

정답 코드

SELECT ID, NAME, HOST_ID
FROM PLACES
WHERE HOST_ID IN (SELECT HOST_ID 
                 FROM PLACES 
                 GROUP BY HOST_ID 
                 HAVING COUNT(*)>=2)
ORDER BY ID;
profile
뭐든지 난 열심히 하지

0개의 댓글