
예전에 풀었던 문제임에도 여전히 어렵다. 또 헤맸다.
그전에도 프로그래머스에서 가장 풀기 어려운 SQL 문제라고 생각했었다.
여전히 같은 부분을 캐치하지 못하고 이전 풀이를 참고하여 여러 번의 시도 끝에 풀이했다.
이래서 복습이 중요한가보다.
이 문제는 크게 3가지 흐름이 있고, 주의해야할 점이 1가지 있다.
car_rental_company_discount_plan의 discount_rate를 참고하여 30일동안 대여시 할인 적용가인 fee를 계산하고, fee가 500000이상, 2000000미만이도록 필터링한다.여기서 주의해야할 부분은 3번이다.
11월에 대여를 제외한 기록의 차량이 11월에 빌릴 수 있는 차량은 아니다.
이게 무슨 소리냐면?
만약 A차량이
2022-09-10 ~ 2022-09-20,
2022-11-10 ~ 2022-11-20
와 같은 대여 기록이 있다고 치자.
사람이 이렇게 눈으로 본다면 당연히 대여하지 못하는 차량으로 분류할 것이다.
여기서 "2022-11-01 ~ 2022-11-30 사이에 대여 기간이 겹치지 않는 기록에 있는 차량중에~"라고 하게되면 A차량의 경우 두번째인 2022-11-10 ~ 2022-11-20기록이 걸러질 것이고, 2022-09-10 ~ 2022-09-20 기록만 남게된다.
이렇게 남은 차량을 대여 가능한 차량으로 본다면 잘못된 필터링을 하게 되는 것이다.
...
예시를 들었더니 더 복잡하게 느껴지는 것 같기도 하다.
아무튼 이때문에 해당 기간과 대여 기간이 겹치는 모든 car_id를 추출한 뒤,
이 car_id들에 포함되지 않는 차량을 필터링해야한다.
나머지는 평소와 같이 JOIN하고 필터링해주면 된다.
WITH rented AS (
SELECT DISTINCT car_id
FROM car_rental_company_rental_history
WHERE start_date <= "2022-11-30" AND end_date >= "2022-11-01"
)
SELECT car_id, c.car_type, round(daily_fee*30*(100-discount_rate)/100) fee
FROM car_rental_company_car c
LEFT JOIN car_rental_company_discount_plan d
ON c.car_type = d.car_type
AND c.car_type in ("세단", "SUV")
AND d.duration_type = "30일 이상"
WHERE car_id NOT IN (SELECT * FROM rented)
AND daily_fee*30*(100-discount_rate)/100 BETWEEN 500000 AND 2000000-1
ORDER BY 3 DESC, 2 ASC, 1 DESC;