huginn muninn

[프로그래머스] 특정 기간동안 대여 가능한 자동차들의 대여비용 구하기 SQL 본문

코딩테스트

[프로그래머스] 특정 기간동안 대여 가능한 자동차들의 대여비용 구하기 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 이런거 되도록 지양하기.