프로그래머스 MySQL Lv.3 (2)

Journey to Data Analyst·2023년 4월 14일
0

프로그래머스 MySQL

목록 보기
5/7
post-thumbnail

요즘 데이터 엔지니어링 인강과 Tableau 대시보드를 하나 만들었더니
본의아니게 프로그래머스 Lv.3 업로드에 소홀하게 되었다.
바로 시작해보도록 하자!

1. 조건에 맞는 사용자와 총 거래금액 조회하기

문제 설명

다음은 중고 거래 게시판 정보를 담은 USED_GOODS_BOARD 테이블과 중고 거래 게시판 첨부파일 정보를 담은 USED_GOODS_FILE 테이블입니다. 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_USER 테이블은 다음과 같으며 USER_IDNICKNAMECITYSTREET_ADDRESS1STREET_ADDRESS2TLNO는 각각 회원 ID, 닉네임, 시, 도로명 주소, 상세 주소, 전화번호를 를 의미합니다.

Column nameTypeNullable
USER_IDVARCHAR(50)FALSE
NICKANMEVARCHAR(100)FALSE
CITYVARCHAR(100)FALSE
STREET_ADDRESS1VARCHAR(100)FALSE
STREET_ADDRESS2VARCHAR(100)TRUE
TLNOVARCHAR(20)FALSE

문제

USED_GOODS_BOARD와 USED_GOODS_USER 테이블에서 완료된 중고 거래의 총금액이 70만 원 이상인 사람의 회원 ID, 닉네임, 총거래금액을 조회하는 SQL문을 작성해주세요.
결과는 총거래금액을 기준으로 오름차순 정렬해주세요.


예시

USED_GOODS_BOARD 테이블이 다음과 같고

BOARD_IDWRITER_IDTITLECONTENTSPRICECREATED_DATESTATUSVIEWS
B0001zkzkdh1캠핑의자가벼워요 깨끗한 상태입니다. 2개250002022-11-29SALE34
B0002miyeon89벽걸이 에어컨엘지 휘센 7평1000002022-11-29SALE55
B0003dhfkzmf09에어팟 맥스에어팟 맥스 스카이 블루 색상 판매합니다.4500002022-11-26DONE67
B0004sangjune1파파야나인 포르쉐 푸쉬카예민하신분은 피해주세요300002022-11-30DONE78
B0005zkzkdh1애플워치7애플워치7 실버 스텐 45미리 판매합니다.7000002022-11-30DONE99

USED_GOODS_USER 테이블이 다음과 같을 때

USER_IDNICKNAMECITYSTREET_ADDRESS1STREET_ADDRESS2TLNO
cjfwls91점심만금식성남시분당구 내정로 185501호01036344964
zkzkdh1후후후성남시분당구 내정로 35가동 1202호01032777543
spdlqj12크크큭성남시분당구 수내로 2062019동 801호01087234922
xlqpfh2잉여킹성남시분당구 수내로 1001-00401064534911
dhfkzmf09찐찐성남시분당구 수내로 13A동 1107호01053422914

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

USER_IDNICKNAMETOTAL_SALES
zkzkdh1후후후700000

Answer

SELECT u.USER_ID, u.NICKNAME, 
       SUM(B.PRICE) AS TOTAL_SALES
FROM USED_GOODS_BOARD b
INNER JOIN USED_GOODS_USER u
ON b.WRITER_ID = u.USER_ID
WHERE b.STATUS = 'DONE'
GROUP BY u.USER_ID 
HAVING TOTAL_SALES >= 700000
ORDER BY TOTAL_SALES;

이 문제는 비교적 간단한? 서브쿼리 없이도 풀이할 수 있다.
다만 WHERE조건과 HAVING 조건에 어떤 것이 들어가야하는지 고민해봐야된다.

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년 10월 16일에 대여 중인 자동차인 경우 '대여중' 이라고 표시하고, 대여 중이지 않은 자동차인 경우 '대여 가능'을 표시하는 컬럼(컬럼명: AVAILABILITY)을 추가하여
자동차 ID와 AVAILABILITY 리스트를 출력하는 SQL문을 작성해주세요.
이때 반납 날짜가 2022년 10월 16일인 경우에도 '대여중'으로 표시해주시고 결과는 자동차 ID를 기준으로 내림차순 정렬해주세요.


예시

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

HISTORY_IDCAR_IDSTART_DATEEND_DATE
142022-09-272022-09-27
232022-10-032022-10-04
322022-10-052022-10-05
412022-10-112022-10-16
532022-10-132022-10-15
622022-10-152022-10-17

2022년 10월 16일에 대여 중인 자동차는 자동차 ID가 1, 2인 자동차이고, 대여 가능한 자동차는 자동차 ID가 3, 4이므로, '대여중' 또는 '대여 가능' 을 표시하는 컬럼을 추가하고, 자동차 ID를 기준으로 내림차순 정렬하면 다음과 같이 나와야 합니다.

CAR_IDAVAILABILITY
4대여 가능
3대여 가능
2대여중
1대여중

Answer

SELECT CAR_ID
     , CASE WHEN SUM(AVAILABILITY) > 0 THEN "대여중"
            ELSE "대여 가능" END AS AVAILABILITY
FROM (SELECT CAR_ID
           , CASE WHEN "2022-10-16" BETWEEN START_DATE AND END_DATE THEN 1
                  ELSE 0 END AS AVAILABILITY
      FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY) AS z
GROUP BY CAR_ID
ORDER BY CAR_ID DESC

문제에서 요구하는 22년 10월 16일에 대여중인 자동차를 '대여중'이라고 반환하기 위해서는
먼저 해당 기간에 대여중인지 파악해야 할 것이다.
따라서 FROM절 서브쿼리에 CAR_ID와 22년 10월 16일이 START_DATE와 END_DATE에 포함되어있는지 확인하는 쿼리를 AVIAILABILITY로 이름지어준 다음,

CAR_ID 별로 대여중이면 1, 대여중이 아니면 0이 반환되기 때문에
이를 GROUP BY로 묶어 준뒤 SUM(AVAILAVILITY)가 1 초과이면 대여중이기 때문에 이를 통해 대여중인지 아닌지 알 수 있을 것이라 생각하고 쿼리를 작성했다.

3. 대여 횟수가 많은 자동차들의 월별 대여 횟수 구하기

문제 설명

다음은 어느 자동차 대여 회사의 자동차 대여 기록 정보를 담은 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년 8월부터 2022년 10월까지 총 대여 횟수가 5회 이상인 자동차들에 대해서 해당 기간 동안의 월별 자동차 ID 별 총 대여 횟수(컬럼명: RECORDS) 리스트를 출력하는 SQL문을 작성해주세요.
결과는 월을 기준으로 오름차순 정렬하고, 월이 같다면 자동차 ID를 기준으로 내림차순 정렬해주세요.
특정 월의 총 대여 횟수가 0인 경우에는 결과에서 제외해주세요.


예시

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

HISTORY_IDCAR_IDSTART_DATEEND_DATE
112022-07-272022-08-02
212022-08-032022-08-04
322022-08-052022-08-05
422022-08-092022-08-12
532022-09-162022-10-15
612022-08-242022-08-30
732022-10-162022-10-19
812022-09-032022-09-07
912022-09-182022-09-19
1022022-09-082022-09-10
1122022-10-162022-10-19
1212022-09-292022-10-06
1322022-10-302022-11-01
1422022-11-052022-11-05
1532022-11-112022-11-11

대여 시작일을 기준으로 총 대여 횟수가 5회 이상인 자동차는 자동차 ID가 1, 2인 자동차입니다.
월 별 자동차 ID별 총 대여 횟수를 구하고 월 오름차순, 자동차 ID 내림차순으로 정렬하면 다음과 같이 나와야 합니다.

MONTHCAR_IDRECORDS
822
812
921
913
1022

Answer

SELECT MONTH(START_DATE) AS MONTH, CAR_ID, COUNT(*) AS RECORDS
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
WHERE START_DATE >= '2022-08-01'
AND START_DATE < '2022-11-01'
AND CAR_ID IN (SELECT CAR_ID FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
               WHERE START_DATE >= '2022-08-01'
               AND START_DATE < '2022-11-01'
               GROUP BY CAR_ID
               HAVING COUNT(CAR_ID) >= 5)
GROUP BY 1, 2
HAVING RECORDS > 0
ORDER BY 1, 2 DESC;

먼저 22년 8월부터 22년 10월까지 대여중인 자동차들의 조건을 구하는데
그 중 총 대여횟수가 5회 이상인 자동차를 알아보기 위해서는
CAR_ID로 GROUPING하여 해당하는 카운트가 5 이상인지 알아보면 됐었다.

따라서 WHERE절의 CAR_ID가 위의 조건에 해당하는지를 반환하는 식을
IN 서브쿼리에 작성한 다음
본 쿼리에도 똑같은 START_DATE 조건을 걸어주고 이를 카운트해주는 것을 RECORDS로 이름지어주어
MONTHRECORDS로 GROUPING해주었다.

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

문제 설명

다음은 식당의 정보를 담은 REST_INFO 테이블입니다. REST_INFO 테이블은 다음과 같으며 
REST_IDREST_NAMEFOOD_TYPEVIEWSFAVORITESPARKING_LOTADDRESSTEL은 식당 ID, 식당 이름, 음식 종류, 조회수, 즐겨찾기수, 주차장 유무, 주소, 전화번호를 의미합니다.

Column nameTypeNullable
REST_IDVARCHAR(5)FALSE
REST_NAMEVARCHAR(50)FALSE
FOOD_TYPEVARCHAR(20)TRUE
VIEWSNUMBERTRUE
FAVORITESNUMBERTRUE
PARKING_LOTVARCHAR(1)TRUE
ADDRESSVARCHAR(100)TRUE
TELVARCHAR(100)TRUE

문제

REST_INFO 테이블에서 음식종류별로 즐겨찾기수가 가장 많은 식당의 음식 종류, ID, 식당 이름, 즐겨찾기수를 조회하는 SQL문을 작성해주세요. 이때 결과는 음식 종류를 기준으로 내림차순 정렬해주세요.


예시

REST_INFO 테이블이 다음과 같을 때

REST_IDREST_NAMEFOOD_TYPEVIEWSFAVORITESPARKING_LOTADDRESSTEL
00001은돼지식당한식1150345734N서울특별시 중구 다산로 149010-4484-8751
00002하이가쯔네일식120034112N서울시 중구 신당동 375-21NULL
00003따띠따띠뜨양식1234023102N서울시 강남구 신사동 627-3 1F02-6397-1023
00004스시사카우스일식1522074230N서울시 서울시 강남구 신사동 627-27010-9394-2554
00005코슌스일식15301123N서울특별시 강남구 언주로153길010-1315-8729

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

FOOD_TYPEREST_IDREST_NAMEFAVORITES
한식00001은돼지식당734
일식00004스시사카우스230
양식00003따띠따띠뜨102

Answer

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

이번에는 각 FOOD_TYPE별로 가장 많은 즐겨찾기(FAVORITE) 수를 가진 값들을 반환하는 쿼리를 작성하면 되는데
이는 IN 서브쿼리로 구현하였다.

이제 Lv.3 업로드까지 끝이 났다.
Lv.4를 풀어야하기 때문에 Lv.4를 푼다음 다시 돌아오도록 하겠다!

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

0개의 댓글