본문 바로가기
카테고리 없음

[프로그래머스] SQL LEVEL2 문제 풀이 모음 (MySQL)

by 윤무무 2023. 4. 16.

1. 최솟값 구하기

SELECT MIN(DATETIME)
FROM ANIMAL_INS

- 컬럼 이름은 일치하지 않아도 되기 때문에 AS를 이용할 필요는 없다.

 

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

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

- 개와 고양이(ANIMAL_TYPE)의 각각의 숫자를 출력 해줘야 하기 때문에 GROUP BY 한다.

- ANIMAL_TYPE과 함께 COUNT를 사용한 컬럼을 출력하면 된다.

 

3. 동명 동물 수 찾기

SELECT NAME, COUNT(NAME) AS COUNT
FROM ANIMAL_INS
WHERE NAME IS NOT NULL
GROUP BY NAME
HAVING COUNT(NAME) > 1
ORDER BY NAME;

- 이름이 없는 동물(=NULL)은 집계에서 제외해야 하기 때문에 WHERE NAME IS NOT NULL 을 적어준다.

- 두 번 이상 쓰인 이름의 여부를 확인하기 위해 GROUP BY NAME으로 묶어주고,  HAVING 절에 COUNT(NAME) 이 1보다 크면(두 번 이상 사용했으면) 이라는 조건을 추가한다.

 

4. 루시와 엘라 찾기

SELECT ANIMAL_ID, NAME, SEX_UPON_INTAKE
FROM ANIMAL_INS
WHERE NAME IN ('Lucy', 'Ella', 'Pickle', 'Rogan', 'Sabrina', 'Mitty');

- NAME이  Lucy, Ella, Pickle, Rogan, Sabrina, Mitty 인 동물을 출력해야 하기 때문에 IN을 사용한다.

- (참고) 괄호 안에 있는 이름이 아닌 애들만 출력하고 싶으면 NOT IN 을 적어주면 된다.

 

5. 이름에 el이 들어가는 동물 찾기

SELECT ANIMAL_ID, NAME
FROM ANIMAL_INS
WHERE ANIMAL_TYPE = 'DOG' AND NAME LIKE '%EL%'
ORDER BY NAME;

- 할머니가 기르던 개 + 이름에 el이 들어가야 한다.

- 따라서 WHERE 절에 'DOG' AND NAME LIKE '%EL%' 조건을 적어준다.

- (참고) LIKE 에서 %는 글자 개수 상관 X, _는  _의 개수만큼 글자 제한

 

6. 동물 수 구하기

SELECT COUNT(*)
FROM ANIMAL_INS

- 동물 보호소에 있는 전체 동물의 수를 구하면 되기 때문에 COUNT를 이용하면 된다.

 

7. 중복 제거하기

SELECT COUNT(DISTINCT NAME) AS COUNT
FROM ANIMAL_INS
WHERE NAME IS NOT NULL

- 이름이 NULL인 경우는 집계하지 않으므로 WHERE 에 NAME IS NOT NULL 조건을 추가해준다.

- 중복을 제거하는 함수는 DISCTINCT 이다. 따라서 DISTINCT로 NAME의 중복을 제거해준 후 COUNT 해주면 된다.

 

 8. 중성화 여부 파악하기

SELECT
    ANIMAL_ID,
    NAME,
    CASE
        WHEN SEX_UPON_INTAKE LIKE 'Neutered%' THEN 'O'
        WHEN SEX_UPON_INTAKE LIKE 'Spayed%' THEN 'O'
    ELSE 'X'
    END AS 중성화
FROM ANIMAL_INS
ORDER BY ANIMAL_ID
SELECT
    ANIMAL_ID,
    NAME,
    CASE WHEN (SEX_UPON_INTAKE LIKE 'Neutered%' OR SEX_UPON_INTAKE LIKE 'Spayed%') THEN 'O'
    ELSE 'X'
    END AS 중성화
FROM ANIMAL_INS
ORDER BY ANIMAL_ID
SELECT ANIMAL_ID, NAME,
IF(SEX_UPON_INTAKE LIKE '%NEUTERED%' OR SEX_UPON_INTAKE LIKE '%SPAYED%','O','X') AS '중성화'
FROM ANIMAL_INS
ORDER BY ANIMAL_ID

- CASE WHEN 을 사용했다. 나는 Neutered, spayed 를 두 번의 케이스에 나눠서 적어줬다.

- 물론 아래처럼 OR을 이용하면 한 문장으로 끝낼 수 있다.

- IF (조건, 조건이 참이면 O, 조건이 거짓이면 X) 라는 걸 이용해서 문제를 해결할 수도 있다.

 

9. NULL 처리하기

SELECT ANIMAL_TYPE, IFNULL(NAME,'No name') AS NAME, SEX_UPON_INTAKE
FROM ANIMAL_INS
ORDER BY ANIMAL_ID;

- IFNULL(A,B) 는 A가 NULL 일 경우 B로 채워준다는 의미이다.

- NAME이 없을 경우 No name 이라고 적어줘야 하기 때문에 IFNULL 을 이용한다.

 

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

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

- HOUR(DATETIME) 을 이용하면 DATETIME의 시간만을 뽑아낼 수 있다.

- BETWEEN을 이용해서 HOUR(DATETIME)이 09시부터 19시 사이에 있는 애들만을 조회한다.

- WHERE 절의 조건을 통해 한 번 걸러진 행들을 GROUP BY로 시간 별로 묶고, COUNT 해준다.

 

11. DATETIME에서 DATE로 형 변환

SELECT ANIMAL_ID, NAME, DATE_FORMAT(DATETIME, '%Y-%m-%d') AS 날짜
FROM ANIMAL_INS

- %Y 년도 4자리, %y 년도 4자리

- %M 월 영문, %m 월 숫자

- %D 일 영문, %d 일 숫자

- 따라서 format의 구조를 '%Y-%m-%d'로 작성해줘야한다.

 

12. 가격이 제일 비싼 식품의 정보 출력하기

SELECT *
FROM FOOD_PRODUCT
ORDER BY PRICE DESC
LIMIT 1
SELECT *
FROM FOOD_PRODUCT
WHERE PRICE = (SELECT MAX(PRICE) FROM FOOD_PRODUCT);

- 위처럼 ORDER BY를 해준후 LIMIT 1을 출력해도 되고

- 아래처럼 서브 쿼리를 이용해도 된다.

 

13. 3월에 태어난 여성 회원 목록 출력하기

SELECT MEMBER_ID, MEMBER_NAME, GENDER, DATE_FORMAT(DATE_OF_BIRTH,'%Y-%m-%d') AS DATE_OF_BIRTH
FROM MEMBER_PROFILE
WHERE MONTH(DATE_OF_BIRTH) = 3 AND GENDER = 'W' AND TLNO IS NOT NULL
ORDER BY MEMBER_ID;

- MONTH(DATE_OF_BIRTH) 를 이용하면 MONTH 만 뽑아낼 수 있다. 이 친구가 3인 애들 + 여성 + NOT NULL 조건

- DATE_FORMAT을 이용해 FORMAT을 변경해준다.

- %Y 년도 4자리, %y 년도 4자리

- %M 월 영문, %m 월 숫자

- %D 일 영문, %d 일 숫자

- 따라서 format의 구조를 '%Y-%m-%d'로 작성해줘야한다.

 

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

SELECT LEFT(PRODUCT_CODE, 2) AS CATEGORY, COUNT(*) AS PRODUCTS
FROM PRODUCT
GROUP BY LEFT(PRODUCT_CODE, 2)

- LEFT(컬럼명, 2)를 적으면 앞 2자리를 가지고 카테고리 코드를 만들 수 있다.

- 카테고리 코드를 가지고 GROUP 을 만들어주고, SELECT 해주면 된다.

- (참고) RIGHT(컬럼명,N)도 가능

 

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

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

- TRUNCATE는 버림이다. TRUNCATE(컬럼명, N)에서 N이 양수면 소수점 자릿수까지 버림, 음수면 정수부까지 버림이다.

- 이 문제는 만원 단위로 상품을 나눠야 하기 때문에 TRUNCATE(PRICE, -4)를 해준다.

- 만원 단위로 나눈 걸 PRICE_GROUP라고 별칭을 지어줬으니 PRICE_GROUP별로 그룹을 나눠주고 COUNT 해준다.

 

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

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

- 두 테이블을 JOIN해준다.

- PRICE와 AMOUNT를 곱해주고, 곱해준 값들을 PRODUCT ID 별로 집계(SUM)해준다.

 

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

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

- USER_ID와 PRODUCT_ID의 쌍을 이뤄서 GROUP BY 해준다.

- 그 개수가 1개 이상인 애들을 조건에 맞게 출력해준다.

 

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

SELECT MCDP_CD AS 진료과코드, COUNT(*) AS 5월예약건수
FROM APPOINTMENT
WHERE APNT_YMD LIKE '2022-05%'
GROUP BY MCDP_CD
ORDER BY 5월예약건수, 진료과코드;

- 2022년 5월 예약환자들 중 진료과 코드별로 GROPU을 지어준다.

 

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

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

- 두 테이블을 JOIN 해준다.

- 성분으로 GROPU을 지어주고, 집계함수를 이용해 총 주문량을 출력해준다.

 

20. 조건에 맞는 도서와 저자 리스트 출력하기

SELECT B.BOOK_ID, A.AUTHOR_NAME, DATE_FORMAT(B.PUBLISHED_DATE, '%Y-%m-%d') AS PUBLISHED_DATE
FROM BOOK B JOIN AUTHOR A
ON B.AUTHOR_ID = A.AUTHOR_ID
WHERE B.CATEGORY = '경제'
ORDER BY PUBLISHED_DATE;

- JOIN을 해준 후 CATEGORY가 경제인 애들을 출력하면 된다.

 

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

SELECT CAR_TYPE, COUNT(*) AS CARS
FROM CAR_RENTAL_COMPANY_CAR
WHERE OPTIONS LIKE '%통풍시트%' OR OPTIONS LIKE '%열선시트%' OR OPTIONS LIKE '%가죽시트%'
GROUP BY CAR_TYPE
ORDER BY CAR_TYPE

- IN을 사용해주면 될 줄 알았는데 모르겠어서 LIKE를 이용했다.

- LIKE로 조건을 만들어준 후 CAR_TYPE별로 GROUP BY해준다.

- (참고) LIKE 에서 %는 글자 개수 상관 X, _는  _의 개수만큼 글자 제한

 

22. 자동차 평균 대여 기간 구하기

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 AVERAGE_DURATION >= 7
ORDER BY AVERAGE_DURATION DESC, CAR_ID DESC;

- DATEDIFF(END, START)를 이용하면 날짜의 차이를 출력할 수 있는데, 이 문제는 마지막 날도 포함해줘야 하므로 +1 해준다.

EX) DATEDIFF(14일,12일) = 2  // 3일 빌렸으니 +1해줘야 함

- CAR_ID 별로 DATEDIFF의 평균을 내주고, ROUND로 반올림해서 풀면 된다.

 

23. 조건에 부합하는 중고거래 상태 조회하기

SELECT BOARD_ID, WRITER_ID, TITLE, PRICE,
    CASE WHEN STATUS = 'SALE' THEN '판매중'
    WHEN STATUS = 'RESERVED' THEN '예약중'
    ELSE '거래완료'
    END AS STATUS
FROM USED_GOODS_BOARD
WHERE CREATED_DATE = '2022-10-05'
ORDER BY BOARD_ID DESC;

- CREATED_DATE가 2022년 10월 5일인 ROW 를 CASE WHEN을 이용해 상태를 바꿔주면 된다.

댓글