코딩테스트
[프로그래머스] 특정 기간동안 대여 가능한 자동차들의 대여비용 구하기 SQL
_maddy
2024. 6. 13. 17:39
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
조건이 많아서 까다로웠던 문제, 하지만 차근차근 조건 정리하면서 코드를 짜면 별로 어렵지 않다.

WITH HISTORY AS (
SELECT DISTINCT CAR_ID
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY AS H
WHERE NOT EXISTS (
SELECT CAR_ID
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY AS H1
WHERE H.CAR_ID=H1.CAR_ID
AND START_DATE <= '2022-11-30'
AND END_DATE >= '2022-11-01')
),
CAR AS (
SELECT CAR_ID, CAR_TYPE, DAILY_FEE
FROM CAR_RENTAL_COMPANY_CAR
WHERE CAR_TYPE IN ('세단', 'SUV')
),
DISCOUNT AS (
SELECT CAR_TYPE, DISCOUNT_RATE
FROM CAR_RENTAL_COMPANY_DISCOUNT_PLAN
WHERE CAR_TYPE IN ('세단', 'SUV')
AND DURATION_TYPE = '30일 이상'
)
SELECT
C.CAR_ID,
C.CAR_TYPE,
ROUND(30 * C.DAILY_FEE * (1 - D.DISCOUNT_RATE / 100.0)) AS FEE
FROM HISTORY AS H
LEFT JOIN CAR AS C ON H.CAR_ID = C.CAR_ID
LEFT JOIN DISCOUNT AS D ON C.CAR_TYPE = D.CAR_TYPE
WHERE
(30 * C.DAILY_FEE * (1 - D.DISCOUNT_RATE / 100.0)) >= 500000
AND (30 * C.DAILY_FEE * (1 - D.DISCOUNT_RATE / 100.0)) < 2000000
ORDER BY
FEE DESC,
C.CAR_TYPE ASC,
C.CAR_ID DESC;
이 문제에서 주어진 데이터가 3개인데, 이걸 다 조인해야해야했따. 그때 마다 where 조건 걸어주면 코드가 더러워지는 게 싫어서 with으로 다 처리해버렸다. 차근차근 코드 분리해서 설명해보겠다.
1. 2022년 11월 1일부터 2022년 11월 30일까지 대여할 수 있는 자동차
WITH HISTORY AS (
SELECT DISTINCT CAR_ID
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY AS H
WHERE NOT EXISTS (
SELECT CAR_ID
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY AS H1
WHERE H.CAR_ID=H1.CAR_ID
AND START_DATE <= '2022-11-30'
AND END_DATE >= '2022-11-01')
),
나한테 좀 까다로웠던 부분, 왜냐면 CAR_RENTAL_COMPANY_RENTAL_HISTORY에 중복으로 들어간 자동차가 있을 것이라고 생각했기 때문에 처음에는 car_id 기준으로 groypby 해준 다음에 end_date의 max 값만 저장했다가 distinct로 바꿔주었다. (헤헷 바보)
그리고 2022년 11월 1일부터 11월 30일 사이에 대여되지 않은 차량의 ID를 찾는 서브쿼리를 구현해주었다. (not exists)
2. 세단이랑 suv만 car_rental_company_car 에서 가져오기
CAR AS (
SELECT CAR_ID, CAR_TYPE, DAILY_FEE
FROM CAR_RENTAL_COMPANY_CAR
WHERE CAR_TYPE IN ('세단', 'SUV')
),
어차피 세단이랑 suv만 필요하니까 조건 걸어주기.
3. 30일 이상, 세단 suv 만 car_rental_company_discount_plan에서 가져오기
DISCOUNT AS (
SELECT CAR_TYPE, DISCOUNT_RATE
FROM CAR_RENTAL_COMPANY_DISCOUNT_PLAN
WHERE CAR_TYPE IN ('세단', 'SUV')
AND DURATION_TYPE = '30일 이상'
)
여기도 마찬가지, 30일 이상인 할인율만 가져오면 되니까 30일 이상, 그리고 suv, 세단만 가져오기
4. 조인
SELECT
C.CAR_ID,
C.CAR_TYPE,
ROUND(30 * C.DAILY_FEE * (1 - D.DISCOUNT_RATE / 100.0)) AS FEE
FROM HISTORY AS H
LEFT JOIN CAR AS C ON H.CAR_ID = C.CAR_ID
LEFT JOIN DISCOUNT AS D ON C.CAR_TYPE = D.CAR_TYPE
WHERE
(30 * C.DAILY_FEE * (1 - D.DISCOUNT_RATE / 100.0)) >= 500000
AND (30 * C.DAILY_FEE * (1 - D.DISCOUNT_RATE / 100.0)) < 2000000
ORDER BY
FEE DESC,
C.CAR_TYPE ASC,
C.CAR_ID DESC;
30일 대여 시 할인율 계산해주고, 50만원 이상, 200만원 이하인 자동차 걸러내기, 그리고 꼭! 오름차순, 내림차순 조건 걸어주기.
코드 구현 시 꼭 지키려고 했던 것,
- alias 꼭 as 로 써주기 : 코드 읽는 사람으로 하여금 as 뒤에 이름써있는게 더 눈에 들어옴.
- 들여쓰기 : 그냥 이건 내 성격. 이것도 사실 가독성이 좋기 때문에.
- 대문자
- alias 만 봐도 어떤 테이블인지 알도록 이름지어주기 a, a1 이런거 되도록 지양하기.