본문 바로가기

IT/SQL

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

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-01~2022-11-30 까지 대여 가능하고 

30일간 대여 금액이 50만원 이상 200만원 미만인 자동차 조회 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
SELECT * 
FROM (
    SELECT A.CAR_ID
          ,C.CAR_TYPE
          ,FLOOR(A.DAILY_FEE * 30 * ((100 - COALESCE(RTRIM(C.DISCOUNT_RATE, '%'), '0')) / 100 )) FEE
    FROM   CAR_RENTAL_COMPANY_CAR A
    INNER JOIN (SELECT D.CAR_ID
                      ,SUM(CASE WHEN (TO_DATE('20221101','YYYYMMDD') BETWEEN D.START_DATE AND D.END_DATE
                                 OR TO_DATE('20221130','YYYYMMDD') BETWEEN D.START_DATE AND D.END_DATE
OR (
                                       D.START_DATE >= TO_DATE('20221101','YYYYMMDD')
                                       AND TO_DATE('20221130','YYYYMMDD') >= D.END_DATE
                                     )
) THEN 1 
                       ELSE 0 END) VALID_CHK
                FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY D
                GROUP BY D.CAR_ID
                ) B ON A.CAR_ID = B.CAR_ID   
                    AND B.VALID_CHK = 0
    LEFT OUTER JOIN CAR_RENTAL_COMPANY_DISCOUNT_PLAN C ON A.CAR_TYPE = C.CAR_TYPE
                                                      AND C.DURATION_TYPE = '30일 이상'
    WHERE A.CAR_TYPE IN ('SUV''세단')
    ) E
WHERE E.FEE >= 500000
AND   2000000 > E.FEE
ORDER BY E.FEE DESC, E.CAR_TYPE ASC, E.CAR_ID DESC

cs

RTRIM, REGEXP_REPLACE

DISCOUNT_RATE 만 숫자로 줬어도 좀 깔끔해보였을 텐데 말인데... 아쉽네요 

RTIRM은 우측의 문자나 공백을 제거할 때 많이 사용하는 함수입니다. 

 

할인율 컬림이 문자니까 컬럼에 % 말고도 다른 문자가 들어갈수도 있겠죠? 

%말고 퍼센트 또는 PERCENT, ' 퍼센트'(퍼센트에 공백 넣은 버전)

이런 데이터가 들어와도 잘 돌아가게 하려면 

 

REGEXP_REPLACE(C.DISCOUNT_RATE, '[^0-9]','')

 

정규식 사용해서 숫자 빼고는 다 날리고 사용하셔도 됩니다. 

 

< 사용을 지양하는 이유

WITH 절로 빼서 처리해도 되지만 WITH 절로 빼면 디비 별로 분기처리 하는 게 번거로워서 JOIN으로 해결할 수 있으면 최대한 JOIN을 씁니다. 속도 이슈가 발생한다거나, 가독성이 너무 떨어지면 분기처리 해야 합니다...!

 

2022-11-01~2022-11-30 동안에 대여가능해야 하니까

시작일이 2022-11-01~2022-11-30 사이에 없고, 

종료일이 2022-11-01~2022-11-30  사이에 없고

시작일 종료일 사이에 2022-11-01~2022-11-30이 포함되지 않아야 합니다.

(마지막 경우를 처리 하지 않아도 정답처리가 됩니다. 저도 설명 적다가 생각나서  10번째 줄부터 추가하였습니다)

 

비교할 떄 < 를 사용하지 않고 컬럼 위치를 바꿔서 > 로 사용하는 것은 

마이 바티스를 이용할 때 < 를 사용하려면 <![CDATA[<]]>  이런 식으로 처리 해줘야 합니다. 

 

귀찮다고 쿼리 전체를 감싸면 if 나 foreach 등 다른 함수가 안 먹기 때문에 유의하여야 합니다. 

유의한다 하더라도 한 두개 씩 빠트리는 경우가 있기 때문에 > 으로 사용할 수 있도록 컬럼 위치나 변수 위치를 바꿔주는 편입니다. 

 

이번 같은 경우는 자동차 종류가 두 가지라 IN 으로 처리할 필요는 없지만 

보통은 문제와 같이 자동차 종류를 고정하는 게 아니라 사용자가 선택한 자동차의 종류를 보여주는 경우가 많기 때문에 

IN 절을 사용하여 사용자가 선택한 자동차 종류를 뿌려줍니다.