프로그래머스 MySQL Lv.1

Journey to Data Analyst·2023년 3월 26일
0

프로그래머스 MySQL

목록 보기
1/7

오랜만에 SQL 문제풀이로 돌아왔다!

태블로를 조금 덜하는 대신,
요즘에는 MySQL 문제풀이와 데이터 분석 독서에 집중하고 있던 찰나에
프로그래머스에 새로운 문제들이 추가되어 다시 한번 풀어보게 되었다.

그래서 이번에도 꾸준히 문제를 레벨 별로 풀어보고
기록에 남길만한 문제들을 올려보려고 한다.

Lv.1과 Lv.2는 필요한 설명만 할 생각이다.

Let's Go!

🚘 1. 특정 옵션이 포함된 자동차 리스트 구하기

문제 설명

다음은 어느 자동차 대여 회사에서 대여중인 자동차들의 정보를 담은 CAR_RENTAL_COMPANY_CAR 테이블입니다. 
CAR_RENTAL_COMPANY_CAR 테이블은 아래와 같은 구조로 되어있으며, 

CAR_IDCAR_TYPEDAILY_FEEOPTIONS 는 각각 자동차 ID, 자동차 종류, 일일 대여 요금(원), 자동차 옵션 리스트를 나타냅니다.

Column nameTypeNullable
CAR_IDINTEGERFALSE
CAR_TYPEVARCHAR(255)FALSE
DAILY_FEEINTEGERFALSE
OPTIONSVARCHAR(255)FALSE

자동차 종류는 '세단', 'SUV', '승합차', '트럭', '리무진' 이 있습니다. 자동차 옵션 리스트는 콤마(',')로 구분된 키워드 리스트(옵션 리스트 값 예시: '열선시트', '스마트키', '주차감지센서')로 되어있으며, 키워드 종류는 '주차감지센서', '스마트키', '네비게이션', '통풍시트', '열선시트', '후방카메라', '가죽시트' 가 있습니다.


문제

CAR_RENTAL_COMPANY_CAR 테이블에서 '네비게이션' 옵션이 포함된 자동차 리스트를 출력하는 SQL문을 작성해주세요. 결과는 자동차 ID를 기준으로 내림차순 정렬해주세요.


예시

예를 들어 CAR_RENTAL_COMPANY_CAR 테이블이 다음과 같다면

CAR_IDCAR_TYPEDAILY_FEEOPTIONS
1세단16000가죽시트,열선시트,후방카메라
2SUV14000스마트키,네비게이션,열선시트
3SUV22000주차감지센서,후방카메라,네비게이션

'네비게이션' 옵션이 포함된 자동차는 자동차 ID가 2, 3인 자동차이고, 자동차 ID를 기준으로 내림차순 정렬하면 다음과 같은 결과가 나와야 합니다.


Answer

SELECT CAR_ID, CAR_TYPE, DAILY_FEE, OPTIONS FROM CAR_RENTAL_COMPANY_CAR
WHERE OPTIONS LIKE '%네비게이션%'
ORDER BY CAR_ID DESC;

간단하게 LIKE 구문과 정규표현식을 쓰면 되는 문제였다.

🚙 2. 자동차 대여 기록에서 장기/단기 대여 구분하기

문제 설명

다음은 어느 자동차 대여 회사의 자동차 대여 기록 정보를 담은 
CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블입니다. 

CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블은 아래와 같은 구조로 되어있으며, 
HISTORY_IDCAR_IDSTART_DATEEND_DATE 는 각각 자동차 대여 기록 ID, 자동차 ID, 대여 시작일, 대여 종료일을 나타냅니다.

Column nameTypeNullable
HISTORY_IDINTEGERFALSE
CAR_IDINTEGERFALSE
START_DATEDATEFALSE
END_DATEDATEFALSE

문제

CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블에서 대여 시작일이 2022년 9월에 속하는 대여 기록에 대해서 대여 기간이 30일 이상이면 '장기 대여' 그렇지 않으면 '단기 대여' 로 표시하는 컬럼(컬럼명: RENT_TYPE)을 추가하여 대여기록을 출력하는 SQL문을 작성해주세요. 결과는 대여 기록 ID를 기준으로 내림차순 정렬해주세요.


예시

예를 들어 CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블이 다음과 같다면

HISTORY_IDCAR_IDSTART_DATEEND_DATE
142022-09-272022-11-27
232022-10-032022-11-04
322022-09-052022-09-05
412022-09-012022-09-30
532022-09-162022-10-15

2022년 9월의 대여 기록 중 '장기 대여' 에 해당하는 기록은 대여 기록 ID가 1, 4인 기록이고, '단기 대여' 에 해당하는 기록은 대여 기록 ID가 3, 5 인 기록이므로 대여 기록 ID를 기준으로 내림차순 정렬하면 다음과 같이 나와야 합니다.

HISTORY_IDCAR_IDSTART_DATEEND_DATERENT_TYPE
532022-09-162022-10-13단기 대여
412022-09-012022-09-30장기 대여
322022-09-052022-09-05단기 대여
142022-09-272022-10-26장기 대여

주의사항

START_DATE와 END_DATE의 경우 예시의 데이트 포맷과 동일해야 정답처리 됩니다.


Answer

SELECT HISTORY_ID, CAR_ID,
    DATE_FORMAT(START_DATE, '%Y-%m-%d') AS START_DATE, 
    DATE_FORMAT(END_DATE, '%Y-%m-%d') AS END_DATE,
    CASE 
        WHEN DATEDIFF(END_DATE, START_DATE) >= 29 THEN '장기 대여'
    ELSE '단기 대여'
    END AS RENT_TYPE
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
WHERE DATE_FORMAT(START_DATE, '%Y-%m') = '2022-09'
ORDER BY HISTORY_ID DESC;

여기서 가장 문제는 START_DATE에 빌린 날짜가 포함되므로 30일이 아니라 29일을
'장기 대여'에 적용시켜야한다는 것이다.

또한 프로그래머스 문제의 특징으로 Date 타입의 값들이 전부 시-분-초까지 등장해
DATE_FORMAT 함수로 형태를 변형해주어야한다.

🍦 3. 과일로 만든 아이스크림 고르기

문제 설명

다음은 아이스크림 가게의 상반기 주문 정보를 담은 FIRST_HALF 테이블과 아이스크림 성분에 대한 정보를 담은 ICECREAM_INFO 테이블입니다. FIRST_HALF 테이블 구조는 다음과 같으며, SHIPMENT_IDFLAVORTOTAL_ORDER 는 각각 아이스크림 공장에서 아이스크림 가게까지의 출하 번호, 아이스크림 맛, 상반기 아이스크림 총주문량을 나타냅니다. FIRST_HALF 테이블의 기본 키는 FLAVOR입니다.

NAMETYPENULLABLE
SHIPMENT_IDINT(N)FALSE
FLAVORVARCHAR(N)FALSE
TOTAL_ORDERINT(N)FALSE

ICECREAM_INFO 테이블 구조는 다음과 같으며, FLAVORINGREDITENT_TYPE 은 각각 아이스크림 맛, 아이스크림의 성분 타입을 나타냅니다. INGREDIENT_TYPE에는 아이스크림의 주 성분이 설탕이면 sugar_based라고 입력되고, 아이스크림의 주 성분이 과일이면 fruit_based라고 입력됩니다. ICECREAM_INFO의 기본 키는 FLAVOR입니다. ICECREAM_INFO테이블의 FLAVOR는 FIRST_HALF 테이블의 FLAVOR의 외래 키입니다.

NAMETYPENULLABLE
FLAVORVARCHAR(N)FALSE
INGREDIENT_TYPEVARCHAR(N)FALSE

문제

상반기 아이스크림 총주문량이 3,000보다 높으면서 아이스크림의 주 성분이 과일인 아이스크림의 맛을 총주문량이 큰 순서대로 조회하는 SQL 문을 작성해주세요.


예시

예를 들어 FIRST_HALF 테이블이 다음과 같고

SHIPMENT_IDFLAVORTOTAL_ORDER
101chocolate3200
102vanilla2800
103mint_chocolate1700
104caramel2600
105white_chocolate3100
106peach2450
107watermelon2150
108mango2900
109strawberry3100
110melon3150
111orange2900
112pineapple2900

ICECREAM_INFO 테이블이 다음과 같다면

FLAVORINGREDIENT_TYPE
chocolatesugar_based
vanillasugar_based
mint_chocolatesugar_based
caramelsugar_based
white_chocolatesugar_based
peachfruit_based
watermelonfruit_based
mangofruit_based
strawberryfruit_based
melonfruit_based
orangefruit_based
pineapplefruit_based

상반기 아이스크림 총주문량이 3,000보다 높은 아이스크림 맛은 chocolate, strawberry, melon, white_chocolate입니다. 이 중에 아이스크림의 주 성분이 과일인 아이스크림 맛은 strawberry와 melon이고 총주문량이 큰 순서대로 아이스크림 맛을 조회하면 melon, strawberry 순으로 조회되어야 합니다. 따라서 SQL 문을 실행하면 다음과 같이 나와야 합니다.

FLAVOR
melon
---
strawberry

Answer

SELECT f.FLAVOR FROM FIRST_HALF f
LEFT JOIN ICECREAM_INFO i
ON f.FLAVOR = i.FLAVOR
WHERE f.TOTAL_ORDER > 3000
AND i.INGREDIENT_TYPE = 'fruit_based'
ORDER BY f.TOTAL_ORDER DESC;

정확한 JOIN 구문과 조건을 적어주면 된다.

🏭 4. 경기도에 위치한 식품창고 목록 출력하기

문제 설명

다음은 식품창고의 정보를 담은 FOOD_WAREHOUSE 테이블입니다. FOOD_WAREHOUSE 테이블은 다음과 같으며 WAREHOUSE_IDWAREHOUSE_NAMEADDRESSTLNOFREEZER_YN는 창고 ID, 창고 이름, 창고 주소, 전화번호, 냉동시설 여부를 의미합니다.

Column nameTypeNullable
WAREHOUSE_IDVARCHAR(10)FALSE
WAREHOUSE_NAMEVARCHAR(20)FALSE
ADDRESSVARCHAR(100)TRUE
TLNOVARCHAR(20)TRUE
FREEZER_YNVARCHAR(1)TRUE

문제

FOOD_WAREHOUSE 테이블에서 경기도에 위치한 창고의 ID, 이름, 주소, 냉동시설 여부를 조회하는 SQL문을 작성해주세요. 이때 냉동시설 여부가 NULL인 경우, 'N'으로 출력시켜 주시고 결과는 창고 ID를 기준으로 오름차순 정렬해주세요.


예시

FOOD_WAREHOUSE 테이블이 다음과 같을 때

WAREHOUSE_IDWAREHOUSE_NAMEADDRESSTLNOFREEZER_YN
WH0001창고_경기1경기도 안산시 상록구 용담로 141031-152-1332Y
WH0002창고_충북1충청북도 진천군 진천읍 씨제이로 110043-623-9900Y
WH0003창고_경기2경기도 이천시 마장면 덕평로 811031-221-7241NULL
WH0004창고_경기3경기도 김포시 대곶면 율생중앙로205번길031-671-1900N
WH0005창고_충남1충청남도 천안시 동남구 광덕면 신덕리1길 9041-876-5421Y

SQL을 실행하면 다음과 같이 출력되어야 합니다.

WAREHOUSE_IDWAREHOUSE_NAMEADDRESSFREEZER_YN
WH0001창고_경기1경기도 안산시 상록구 용담로 141Y
WH0003창고_경기2경기도 이천시 마장면 덕평로 811N
WH0004창고_경기3경기도 김포시 대곶면 율생중앙로205번길N

Answer

SELECT WAREHOUSE_ID, WAREHOUSE_NAME, ADDRESS,
       CASE WHEN FREEZER_YN IS NULL THEN 'N'
       ELSE FREEZER_YN
       END AS FREEZER_YN
FROM FOOD_WAREHOUSE
WHERE ADDRESS LIKE '경기%'
ORDER BY WAREHOUSE_ID ASC;

-- 내 답안
SELECT WAREHOUSE_ID, WAREHOUSE_NAME, ADDRESS, IFNULL(FREEZER_YN, 'N')
FROM FOOD_WAREHOUSE
WHERE WAREHOUSE_NAME LIKE '%경기%'
ORDER BY WAREHOUSE_ID

이번에는 두 개의 답안을 작성해보았다.
IFNULL로 간단하게 NULL 값을 'N'으로 나타나는 경우와
CASE WHEN을 사용해 좀 더 구체적으로 나타내는 경우이다.

🤝🏻 5. 조건에 부합하는 중고거래 댓글 조회하기

문제 설명

다음은 중고거래 게시판 정보를 담은 USED_GOODS_BOARD 테이블과 중고거래 게시판 첨부파일 정보를 담은 USED_GOODS_REPLY 테이블입니다. USED_GOODS_BOARD 테이블은 다음과 같으며 BOARD_IDWRITER_IDTITLECONTENTSPRICECREATED_DATESTATUSVIEWS은 게시글 ID, 작성자 ID, 게시글 제목, 게시글 내용, 가격, 작성일, 거래상태, 조회수를 의미합니다.

Column nameTypeNullable
BOARD_IDVARCHAR(5)FALSE
WRITER_IDVARCHAR(50)FALSE
TITLEVARCHAR(100)FALSE
CONTENTSVARCHAR(1000)FALSE
PRICENUMBERFALSE
CREATED_DATEDATEFALSE
STATUSVARCHAR(10)FALSE
VIEWSNUMBERFALSE

USED_GOODS_REPLY 테이블은 다음과 같으며 REPLY_IDBOARD_IDWRITER_IDCONTENTSCREATED_DATE는 각각 댓글 ID, 게시글 ID, 작성자 ID, 댓글 내용, 작성일을 의미합니다.

Column nameTypeNullable
REPLY_IDVARCHAR(10)FALSE
BOARD_IDVARCHAR(5)FALSE
WRITER_IDVARCHAR(50)FALSE
CONTENTSVARCHAR(1000)TRUE
CREATED_DATEDATEFALSE

문제

USED_GOODS_BOARD와 USED_GOODS_REPLY 테이블에서 2022년 10월에 작성된 게시글 제목, 게시글 ID, 댓글 ID, 댓글 작성자 ID, 댓글 내용, 댓글 작성일을 조회하는 SQL문을 작성해주세요. 결과는 댓글 작성일을 기준으로 오름차순 정렬해주시고, 댓글 작성일이 같다면 게시글 제목을 기준으로 오름차순 정렬해주세요.


예시

USED_GOODS_BOARD 테이블이 다음과 같고

BOARD_IDWRITER_IDTITLECONTENTSPRICECREATED_DATESTATUSVIEWS
B0001kwag98반려견 배변패드 팝니다정말 저렴히 판매합니다. 전부 미개봉 새상품입니다.120002022-10-01DONE250
B0002lee871201국내산 볶음참깨직접 농사지은 참깨입니다.30002022-10-02DONE121
B0003goung12배드민턴 라켓사놓고 방치만 해서 팝니다.90002022-10-02SALE212
B0004keel1990디올 귀걸이신세계강남점에서 구입. 정품 아닐시 백퍼센트 환불1300002022-10-02SALE199
B0005haphli01스팸클래식 팔아요유통기한 2025년까지에요100002022-10-02SALE121

USED_GOODS_REPLY 테이블이 다음과 같을 때

REPLY_IDBOARD_IDWRITER_IDCONTENTSCREATED_DATE
R000000001B0001s2s2123구매하겠습니다. 쪽지 드립니다.2022-10-02
R000000002B0002hoho1112쪽지 주세요.2022-10-03
R000000003B0006hwahwa2삽니다. 연락주세요.2022-10-03
R000000004B0007hong02예약중2022-10-06
R000000005B0009hanju23구매완료2022-10-07

SQL을 실행하면 다음과 같이 출력되어야 합니다.

TITLEBOARD_IDREPLY_IDWRITER_IDCONTENTSCREATED_DATE
반려견 배변패드 팝니다B0001R000000001s2s2123구매하겠습니다. 쪽지 드립니다.2022-10-02
국내산 볶음참깨B0002R000000002hoho1112쪽지 주세요.2022-10-03

주의사항

CREATED_DATE의 포맷이 예시의 포맷과 일치해야 정답처리 됩니다.


Answer

SELECT b.TITLE, r.BOARD_ID, r.REPLY_ID, r.WRITER_ID, r.CONTENTS,
       DATE_FORMAT(r.CREATED_DATE, '%Y-%m-%d') AS CREATED_DATE
FROM USED_GOODS_BOARD b
JOIN USED_GOODS_REPLY r
ON b.BOARD_ID = r.BOARD_ID
WHERE b.CREATED_DATE LIKE '2022-10%'
ORDER BY 6 ASC, 1 ASC;

이 문제는 Lv.1 이라고 하기에는 좀 애매한 문제였다.
일단 작성된 게시글과 답글이 달린 게시글이 다르기때문에 그것을 신경써주어 쿼리를 짜주어야 하고
두번째는 LEFT JOIN을 사용했을 때는 정답처리가 되지 않아
혹시나 하는 마음에 확실한 INNER JOIN을 사용하니 정답처리가 되었다.

이 문제는 좀 더 연구해봐야할 것 같다.

다음에는 Lv.2로 돌아오겠다!!

profile
성장하는 주니어 데이터 분석가(Tableau, SQL and Python)

0개의 댓글