본문 바로가기
프로그래밍/SQL, Hive, SAS 관련 정보

[SQL문제풀이] Join Key의 처리

by TrillionNT 2025. 3. 9.

2025.02.24 - [프로그래밍/SQL, Hive, SAS 관련 정보] - [SQL] Table of Contents


프로그래머스: 자동차 대여 기록 별 대여 금액 구하기

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

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

 

디테일한 부분에서 꽤나 까다로운 문제입니다. 일단 할인이 되지않는 경우에는 할인테이블에 정보가 없기 때문에 이것을 처리해주어야 하고(NVL로 처리할 수 있죠) join의 조건에 2개가 걸리는데 조건의 raw 상태에서 바로 조건을 걸 수가 없습니다. 

 

여기서 실수하기 쉬운 포인트 몇 가지를 짚어보면

1) 대여기간은 start - end + 1 이다 : 당일 하루만 썼더라도 1일이니까요

2) join key가 그대로 주어지지 않았으므로 가공해서 join key를 만들어야 한다 : 특히 7일 미만인 경우에는 null이 들어간다는 것을 인지

3) round, floor의 작업 : 연산을 통해 어떤 수치형 칼럼을 만들었을 때 이 칼럼의 자리수에 대한 요구조건이 있는지 체크

이 문제에서는 크게 문제가 되지 않았지만 join의 main table로 사용하고 있는 CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블은 car_id 관점에서는 중복이 존재할 수 있다는 점을 인지하고 있어야합니다. 지금은 원하는 output이 history_id별 산출물이었기 때문에 car_id에 중복을 허용하는 output이었지만 만일 원하는 output이 car_id별 산출물이라면 중복제거와 관련된 추가 처리를 해주어야 할 겁니다. 

 

MySQL 코드로 구성한 정답은 아래와 같습니다. 

select history_id, FEE
from
(select t.history_id, round(t.daily_fee*t.len*(1-ifnull(p.discount_rate,0)/100)) FEE, t.car_type
from
    (SELECT h.HISTORY_ID, h.CAR_ID, c.CAR_TYPE, c.DAILY_FEE, Datediff(h.END_DATE, h.START_DATE)+1 len
           , CASE WHEN Datediff(h.END_DATE, h.START_DATE) + 1 >= 90 THEN '90일 이상'
                  WHEN Datediff(h.END_DATE, h.START_DATE) + 1 >= 30 THEN '30일 이상'
                  WHEN Datediff(h.END_DATE, h.START_DATE) + 1 >= 7 THEN '7일 이상'
                  END AS DURATION_TYPE
    from CAR_RENTAL_COMPANY_RENTAL_HISTORY h
    left join CAR_RENTAL_COMPANY_CAR c on h.car_id=c.car_id) t
left join CAR_RENTAL_COMPANY_DISCOUNT_PLAN p on t.car_type=p.car_type and t.duration_type=p.duration_type
order by t.daily_fee*t.len*(1-ifnull(p.discount_rate,0)/100) desc, t.history_id desc) tp
where car_type='트럭';

 

여기서 조금 더 개선한다면 where조건으로 트럭 조건을 나중에 빼지 않고 우선적으로 on조건에서 처리하는 방법도 있습니다.