본문 바로가기
[업무 지식]/MySQL

[기간에 포함되지 않는 날짜] 특정 기간동안 대여 가능한 자동차들의 대여비용 구하기

by 에디터 윤슬 2024. 10. 18.
 

링크

https://school.programmers.co.kr/learn/courses/30/lessons/157339

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제

CAR_RENTAL_COMPANY_CAR 테이블과 CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블과 CAR_RENTAL_COMPANY_DISCOUNT_PLAN 테이블에서 자동차 종류가 '세단' 또는 'SUV' 인 자동차 중 2022년 11월 1일부터 2022년 11월 30일까지 대여 가능하고 30일간의 대여 금액이 50만원 이상 200만원 미만인 자동차에 대해서 자동차 ID, 자동차 종류, 대여 금액(컬럼명: FEE) 리스트를 출력하는 SQL문을 작성해주세요. 결과는 대여 금액을 기준으로 내림차순 정렬하고, 대여 금액이 같은 경우 자동차 종류를 기준으로 오름차순 정렬, 자동차 종류까지 같은 경우 자동차 ID를 기준으로 내림차순 정렬해주세요.

정답 1

with type as (
    select *
    from CAR_RENTAL_COMPANY_CAR
    where car_type in ('SUV', '세단')
), not_car as (
    select *
    from CAR_RENTAL_COMPANY_RENTAL_HISTORY
    where date_format(end_date, '%Y-%m') = '2022-11'
    or date_format(start_date, '%Y-%m') = '2022-11'
    or date_format(end_date, '%Y-%m') > '2022-11' and date_format(start_date, '%Y-%m') < '2022-11'
), result as (
    select distinct t.car_id,
            car_type,
            daily_fee as fee
    from type t
    join CAR_RENTAL_COMPANY_RENTAL_HISTORY c
    on t.car_id = c.car_id
    where c.car_id not in (select car_id from not_car)
    and (daily_fee * 30 >= 500000 and daily_fee * 30 < 2000000)
    order by daily_fee desc, car_type, car_id desc
)
select r.car_id, 
        r.car_type,
        floor(r.fee * (1 - c.discount_rate / 100) * 30) as fee
from result r
join CAR_RENTAL_COMPANY_DISCOUNT_PLAN c
on r.car_type = c.car_type and c.duration_type = '30일 이상'

# 시작일이 11월 1일보다 적으면서 & 종료일이 11월 30일보다 많으면 X
# 시작일이 11월 1일과 11월 30일 사이에 있으면 X
# 종료일이 11월 1일과 11월 30일 사이에 있으면 X

정답 2

WITH CANT_RENTAL AS (
    SELECT DISTINCT CAR_ID 
    FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
    WHERE 
    DATE_FORMAT(START_DATE, '%Y-%m') = '2022-11' OR 
    DATE_FORMAT(END_DATE, '%Y-%m') = '2022-11' OR 
    (START_DATE < '2022-11-01' AND END_DATE >= '2022-12-01')
),
DISCOUNT AS (
    SELECT CAR_TYPE, DISCOUNT_RATE 
    FROM CAR_RENTAL_COMPANY_DISCOUNT_PLAN
    WHERE DURATION_TYPE	= '30일 이상'
)
SELECT C.CAR_ID, C.CAR_TYPE, 
CONVERT((C.DAILY_FEE * 30) * (100 - D.DISCOUNT_RATE) / 100 , UNSIGNED) FEE
FROM CAR_RENTAL_COMPANY_CAR C JOIN DISCOUNT D 
ON C.CAR_TYPE = D.CAR_TYPE 
WHERE C.CAR_ID NOT IN (SELECT * FROM CANT_RENTAL)
HAVING FEE BETWEEN 500000 AND 1999999
ORDER BY 3 DESC, 2 ASC , 1 DESC

해설

  • 11월 1일부터 11월 30일까지 대여 가능한 차량 확인:
    • 대여 시작일과 대여 종료일이 11월에 있으면 대여 불가
    •     DATE_FORMAT(START_DATE, '%Y-%m') = '2022-11' OR 
          DATE_FORMAT(END_DATE, '%Y-%m') = '2022-11' 
    • 대여 시작일이 11월 이전이고, 대여 종료일이 11월 이후이면 대여 중이므로 대여 불가
    •     (START_DATE < '2022-11-01' AND END_DATE >= '2022-12-01')

새롭게 이해한 내용

  • 해당 날짜를 구할 때, 컬럼이 둘로 나뉘어져 있을 때는 반대 조건을 with로 빼서 정리해도 이해하기 편하다