MySQL 프로그래머스 | 자동차 대여 기록 별 대여 금액 구하기 (ON과 WHERE절 차이)

    728x90

     

    문제

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

     

    프로그래머스

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

    programmers.co.kr

    • 자동차 종류가 '트럭'인 자동차의 대여 기록에 대해서 
    • 대여 기록 별로 대여 금액(컬럼명: FEE) 구하고
    • 대여 기록 ID와 대여 금액 리스트를 출력하는 SQL문 작성하기
    • 대여 금액을 기준 내림차순, 대여 금액이 같은 경우 대여 기록 ID 기준 내림차순 정렬

     

    테이블

    CAR_RENTAL_COMPANY_CAR
    CAR_RENTAL_COMPANY_RENTAL_HISTORY
    CAR_RENTAL_COMPANY_DISCOUNT_PLAN

     

     

    풀이과정

    • 테이블 조인할 때, 어떤 테이블을 중심으로 어떤 조인을 해야 원하는 결과를 얻을 수 있는지 생각하기
      • CC 테이블과 RH 테이블 → INNER JOIN 하되, CAR_TYPE이 '트럭'일 때만 조인
      • DP 테이블 → LEFT JOIN으로 CAR_TYPE이 '트럭'인 경우에만 조인 (CAR_TYPE이 '트럭'이 아닌 경우에는 모두 NULL 처리 됨)
        • CASE WHEN 문을 사용해 각 대여 기간마다의 할인율 구해주기
        • 이 때 주의할 점! 
          해당 조건문을 ON절에 적어줄 때WHERE 조건절에 따로 빼서 적어줄 때의 결과값이 다름!

     

    ▶ LEFT JOIN의 ON절 사용

    • 각 대여 기간마다의 할인율을 구하기 위해 CASE WHEN 문을 사용하고 있는데
      '7일 미만' 조건에 대해서는 ELSE 부분에 NULL 처리를 하고 있음. 
      • 추후 SELECT문에서 따로 IFNULL 함수를 사용해 할인율을 0으로 만들어줘야 함
    • NULL 처리된 모든 행까지도 빠짐없이 같이 출력되는 모습
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT *, DATEDIFF(RH.END_DATE, RH.START_DATE)+1 DD
    FROM CAR_RENTAL_COMPANY_CAR CC
    JOIN CAR_RENTAL_COMPANY_RENTAL_HISTORY RH ON CC.CAR_ID = RH.CAR_ID AND CC.CAR_TYPE = '트럭'
    LEFT JOIN CAR_RENTAL_COMPANY_DISCOUNT_PLAN DP ON CC.CAR_TYPE = DP.CAR_TYPE  
    AND (CASE WHEN DATEDIFF(RH.END_DATE, RH.START_DATE)+1 BETWEEN 7 AND 29 
                    AND DP.DURATION_TYPE = '7일 이상' THEN DP.DISCOUNT_RATE
                WHEN DATEDIFF(RH.END_DATE, RH.START_DATE)+1 BETWEEN 30 AND 89 
                    AND DP.DURATION_TYPE = '30일 이상' THEN DP.DISCOUNT_RATE
                WHEN DATEDIFF(RH.END_DATE, RH.START_DATE)+1 >= 90 
                    AND DP.DURATION_TYPE = '90일 이상' THEN DP.DISCOUNT_RATE ELSE '' END)
    cs

    확대 샷
    전체 샷

     

    ▶ WHERE절 사용

    • 각 대여 기간마다의 할인율을 구하기 위해 CASE WHEN 문을 사용하고 있는데
      '7일 미만' 조건에 대해서는 ELSE 부분에 NULL 처리를 하고 있음 
    • NULL 처리된 모든 행이 제외되고 출력되는 모습
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT *, DATEDIFF(RH.END_DATE, RH.START_DATE)+1 DD
    FROM CAR_RENTAL_COMPANY_CAR CC
    JOIN CAR_RENTAL_COMPANY_RENTAL_HISTORY RH ON CC.CAR_ID = RH.CAR_ID AND CC.CAR_TYPE = '트럭'
    LEFT JOIN CAR_RENTAL_COMPANY_DISCOUNT_PLAN DP ON CC.CAR_TYPE = DP.CAR_TYPE  
    WHERE (CASE WHEN DATEDIFF(RH.END_DATE, RH.START_DATE)+1 BETWEEN 7 AND 29 
                    AND DP.DURATION_TYPE = '7일 이상' THEN DP.DISCOUNT_RATE
                WHEN DATEDIFF(RH.END_DATE, RH.START_DATE)+1 BETWEEN 30 AND 89 
                    AND DP.DURATION_TYPE = '30일 이상' THEN DP.DISCOUNT_RATE
                WHEN DATEDIFF(RH.END_DATE, RH.START_DATE)+1 >= 90 
                    AND DP.DURATION_TYPE = '90일 이상' THEN DP.DISCOUNT_RATE ELSE '' END)
    cs

     

    # 정답

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    SELECT DISTINCT RH.HISTORY_ID,
           ROUND(CC.DAILY_FEE * (1 - IFNULL(DP.DISCOUNT_RATE,0* 0.01* (DATEDIFF(RH.END_DATE, RH.START_DATE)+1),0) FEE
    FROM CAR_RENTAL_COMPANY_CAR CC
    JOIN CAR_RENTAL_COMPANY_RENTAL_HISTORY RH 
         ON CC.CAR_ID = RH.CAR_ID AND CC.CAR_TYPE = '트럭'
    LEFT JOIN CAR_RENTAL_COMPANY_DISCOUNT_PLAN DP 
         ON CC.CAR_TYPE = DP.CAR_TYPE  
         AND (CASE WHEN DATEDIFF(RH.END_DATE, RH.START_DATE)+1 BETWEEN 7 AND 29 
                        AND DP.DURATION_TYPE = '7일 이상' THEN DP.DISCOUNT_RATE
                   WHEN DATEDIFF(RH.END_DATE, RH.START_DATE)+1 BETWEEN 30 AND 89 
                        AND DP.DURATION_TYPE = '30일 이상' THEN DP.DISCOUNT_RATE
                   WHEN DATEDIFF(RH.END_DATE, RH.START_DATE)+1 >= 90 
                        AND DP.DURATION_TYPE = '90일 이상' THEN DP.DISCOUNT_RATE 
              END) 
    ORDER BY FEE DESC, RH.HISTORY_ID DESC
    cs

    728x90

    댓글