본문 바로가기
SQL

[SQL] 자동차 대여 기록에서 장기/단기 대여 구분하기 [알고 있는 것을 다시 체크해보자]

by itstime0809 2023. 8. 26.
728x90

SQL

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

 

프로그래머스

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

programmers.co.kr

 

쿼리

SELECT
HISTORY_ID,
CAR_ID,
DATE_FORMAT(START_DATE, "%Y-%m-%d") as "START_DATE",
DATE_FORMAT(END_DATE, "%Y-%m-%d") as "END_DATE",
CASE 
    WHEN DATEDIFF(END_DATE, START_DATE) + 1 >= 30 THEN "장기 대여"
    ELSE "단기 대여"
    END AS "RENT_TYPE"
# IF(DATEDIFF(END_DATE, START_DATE) >= 30, "장기 대여", "단기 대여") AS RENT_TYPE
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
WHERE DATE_FORMAT(START_DATE, "%Y-%m") = "2022-09" 
# WHERE START_DATE like "2022-09-%"
ORDER BY HISTORY_ID DESC;

 

설명

 해당 문제는 시간 차이를 계산할 줄 아는지 그리고 세부사항을 체크할 수 있는지 칼럼을 추가하는 방법을 알고 있는지와 같은 내용을 알고 있어야 풀이가 가능했던 문제 같다. 나도 위 문제를  풀 때 세 개 중 세 개 전부 다 몰랐기 때문에 인터넷 검색을 통해서 알아보았다. 그래서 흥미로운 찾아본 내용을 가지고 흥미로웠던 점을 바탕으로 그리고 새롭게 배운 것에 대해 작성해 보려고 한다.

 

 우선 첫 번째로 시간 차이를 계산해야 하는 문제다. 시간 차이를 계산할 때 DATEDIFF를 사용한다. 이때 파라미터가 date1, date2를 기준으로 1-2를 빼준 차이라고 볼 수 있다. 따라서 해당 문제에서 요구하는 것은 대여 기간이 며칠이나 지났는지에 따라 달리 하라는 것이기 때문에 렌트를 시작한 날로부터 렌트가 끝난 날짜의 차이를 구하게 되면 얼마큼 빌렸는지를 알 수 있다. 이로써 시간 차이를 통해 값은 구할 수 있었지만 한 가지 간과한 사실이 있는데 예제의 데이터를 보면 09-01, 09-30 데이터가 존재하는 "장기 대여"로 되어 있다. 왜 그럴까? 장기 대여의 조건은 30일 이상 렌트 했다는 조건이 있어야 하지만 END-START의 차이를 구해보아도 29일이다. 그럼 왜 30일이 되지 않았는데 장기대여 일까? 이는 시작일도 포함해야 되기 때문이다. 보통 30-1일 빼게 되면 29만큼의 차이가 난다. 그렇다는 건 1만큼의 크기를 제외한다는 것과 마찬가지인데 이는 1에 반납하는 것을 포함하지 않았기 때문이다. 생각해 보면 1일에 빌려서 1일 날에 반납한 것도 빌린 걸로 해야 되기 때문이다. 1일 자정 12:58분에 빌리고 1일 자정 12:59분에 반납하더라도 1일이 넘어가진 않았지만 1일에 빌려서 1일에 반납은 한 것으로 보아야 된다는 것이다. 그렇기 때문에 하루를 포함하는 +1을 추가하여 하루를 포함하여 30일 이상이 되었다면 장기대여로 보는 것이다. 따라서 9월 1일에 빌리고 9월 30일에 빌렸어도 1일을 포함한 것이기 때문에 1일을 포함하여 29+1=30 이 되어 30일만큼 빌린 것이 되는 것이다. 또한 +1을 보정하는 대신에 -1을 통해서 0-29를 계산해 29가 넘지 않는다면 '단기', 만약 29를 넘게 된다면 '장기'로 구분할 수 있을 것이다. 왜냐하면 +1을 보정하는 건 하루를 포함한다는 의미에서 보정수로 작용 했지만 -1을 하게 된다면 원래 있던 수들에서 -1만큼 뺏기 때문에 그만큼 일수가 줄어들어 29만큼의 차이를 발생시킨다. 따라서 해당 차이만큼 내에 있다면 서로 1씩 빼서 보정해 주었기 때문에 빌린 일수는 같게 작용되어야 한다. 이는 index 계산을 생각해 보면 되는데 index가 0부터 인 것을 생각해 보면 끝이 29라고 했을 때 총길이는 30이지만 계산 방법 자체가 29-0+1이다. 따라서 29일보다 작다는 얘기는 30일보다 작은 구간을 의미하는 것이며 29보다 크거나 같다는 30일을 포함하여 크거나 같은 것을 의미한다.

 

 두번째로 알아야 하는 사실은 칼럼을 추가하는 방법이다. 처음에 나는 칼럼을 추가해야 하기 때문에 ALTER TABLE [테이블명] ADD 칼럼 VARCHAR(25)와 같은 형식을 추가하고 시작했지만 어째서인지 이렇게 추가하는 방법은 되지 않았다. 그래서 좀 찾아본 결과 ALTER와 CASE를 사용해서 칼럼을 반환하는 것과 목적이 달랐다. ALTER 같은 경우에는 데이터베이스 스키마 자체의 구조를 변경하는 데 사용되고, CASE 같은 경우는 주어진 데이터를 기반으로 계산, 가공하여 반환할 때 사용한다. 그래서 위 문제에서는 일수에 따른 칼럼을 생성하는 게 목적이기 때문에 데이터베이스 스키마 구조 자체를 변경하지 않고 해당 계산된 칼럼만을 반환하는 문제인 것 같다. 그래서 CASE문을 통해서 분기를 했으며 IF문을 사용해서도 분기가 가능하다.