[프로그래머스 SQL] Lv. 1 자동차 대여 기록에서 장기/단기 대여 구분하기
※ 문제
※ 코드
-- 코드를 입력하세요
SELECT HISTORY_ID, CAR_ID,
TO_CHAR(START_DATE, 'YYYY-MM-DD') AS START_DATE,
TO_CHAR(END_DATE, 'YYYY-MM-DD') AS END_DATE,
CASE WHEN END_DATE - START_DATE >= 29 THEN '장기 대여'
ELSE '단기 대여'
END AS RENT_TYPE
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
WHERE EXTRACT(YEAR FROM START_DATE) = 2022 AND EXTRACT(MONTH FROM START_DATE) = 9
ORDER BY HISTORY_ID DESC;
※ 풀이
같은 Lv. 1 문제 사이에서도 난이도 차이가 꽤나 심한 듯 합니다 ㅎㅎ...
다음 2가지 조건을 만족해주면 됩니다.
조건 A : IF(END_DATE - START_DATE >= 29, '장기 대여', '단기 대여')
조건 B : EXTRACT(YEAR FROM START_DATE) = 2022 AND EXTRACT(MONTH FROM START_DATE) = 9
먼저 A부터 보자면 대여일이 30일 이상인 경우 장기 대여, 미만이라면 단기 대여가 되는 RENT_TYPE 속성을 추가해주는 것입니다. 그런데 왜 29일인가? 대출 당일부터 1일이기 때문입니다. 저희는 END - START로 날짜를 구하고 있으므로 만약 당일 - 당일이라면 0이 되게 됩니다. 그러므로 1을 더해줄 필요가 있습니다.
다음으로 B입니다. B는 그냥 시작 날짜가 2022년 9월에 속한 행만 출력하도록 해주면 됩니다.
해답 코드를 보기 전에 몇가지 살펴보고 가겠습니다.
우선 VARCHAR에 대하여.
CHAR, VARCHAR, VARCHAR2의 차이는 간단하게만 정리하겠습니다.
우선 우측으로 갈수록 최신 기술이며 기본적으로 VARCHAR2만 쓰시면 됩니다.
VAR가 들어가 있으면 가변으로 입력된 값에 따라 메모리가 할당됩니다.
다만 괄호 안에 들어가는 인수가 최대값이므로 그를 넘어갈 순 없습니다.
다음으로 인수에 대해서 말해보겠습니다.
우선 ORACLE과 그 외의 DBMS로 나누어 볼 수 있습니다.
ORACLE 외의 DBMS는 VARCHAR2(20)과 같이 작성을 한다면 글자수를 기준으로 20개가 최대치가 됩니다.
ORACLE의 경우 글자수가 아닌 BYTE가 기준이 됩니다. 만약 글자수를 기준으로 하고 싶다면 VARCHAR2(20 CHAR)와 같이 작성하여 주면 됩니다.
기본적으로 문자는 하나에 1BYTE가 할당되지만 한글 같은 경우엔 2BYTE가 할당되는 것으로 알고 있습니다.
즉, VARCHAR2(20)로 작성한다면 다른 DBMS에서는 한글 20개까지 입력이 가능하겠지만 ORACLE에서는 10글자까지만 입력이 가능한 것입니다.
한가지만 더 보자면 조건 A에 대한 연산, 조건 B에 대한 연산 중 무엇을 먼저 하는지가 중요한 경우가 있습니다. 현재 문제같은 경우엔 하나의 코드 블록으로 끝났지만 만약 ALTER TABLE ADD ATTR로 열을 먼저 추가하고 진행하는 경우 문제가 될 수 있습니다.
만약 날짜에 대한 필터링을 한 테이블에 RENT_TYPE 값을 추가한다면
날짜 필터링 연산 + RENT_TYPE 추가 연산 + 날짜 필터링 연산
이렇게 3개의 무거운 연산이 이루어집니다. (물론 1번째에서 걸러진 값의 수만큼 RENT_TYPE 추가 연산량이 감소)
만약 RENT_TYPE 값을 추가하고 날짜에 대한 필터링을 한다면
RENT_TYPE 추가 연산 + 날짜 필터링 연산으로 이루어지게 됩니다.
현재 문제 같은 경우엔 한 코드 블럭으로 완성이 되었고, FROM - WHERE - ... 연산 순서에 따라 가장 효율적으로 연산이 이루어집니다.
물론 해당 문제는 TABLE의 VOLUME이 매우 낮으므로 무슨 순서로 진행을 하든 큰 문제는 없구요.
만약 실무였다면 TABLE의 VOLUME을 보고 적절한 설계를 하는 것이 중요할 것 같습니다.
마지막으로 코드 분석을 하겠습니다.
우선 WHERE 절에서 날짜 필터링 연산을 해줍니다. 역시나 ORACLE이므로 EXTRACT 함수를 사용하여 수행합니다.
마찬가지로 ORDER BY 절도 작성해주고요. (정렬 연산은 마지막에 수행됩니다.)
그리고 프로그래머스는 ADD 연산이 안됩니다. 즉, SELECT 절에서 다 해결을 해야해요.
그래서 SELECT 절에 CASE WHEN END로 RENT_TYPE을 만들어 줍니다.
참고로 ORACLE에는 CASE와 DECODE가 있는데 DECODE는 값이 '일치'하는 경우만 처리할 수 있으므로 부등호 연산이 필요한 경우 오직 CASE 만으로 처리가 가능합니다.
(MySQL 같은 경우 그냥 IF 문 쓰면 됩니다.)