프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
조금 헷갈릴 수도 있는 문제라 들고 왔어요
저도 처음에는 풀면서 뭐지?.. 했던 문제였는데 같이 한 번 살펴봐요!
문제 분석
의식의 흐름대로라면
TO_DATE('2022-10-16', 'YYYY-MM-DD') BETWEEN START_DATE AND ENT_DATE
위 조건에 해당하는 CAR_ID를 가져와서 CASE WHEN 구문을 통해 '대여 가능' 또는 '대여중'으로 표시하면 되겠지라고 간단하게 생각했는데, 먼저 데이터를 보시죠!
SELECT *
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
ORDER BY CAR_ID
RESULT :
history_id | car_id | start_date | end_date | availability |
517 | 2 | 2022-08-05 00:00:00 | 2022-08-07 00:00:00 | 대여 가능 |
534 | 2 | 2022-08-09 00:00:00 | 2022-08-09 00:00:00 | 대여 가능 |
537 | 2 | 2022-08-10 00:00:00 | 2022-08-20 00:00:00 | 대여 가능 |
685 | 2 | 2022-10-10 00:00:00 | 2023-01-11 00:00:00 | 대여중 |
결과 데이터 중 일부를 보면 2번 차량에 대해 위 표를 기준으로
3건의 AVAILABILITY 컬럼값은 '대여 가능'이며 마지막 데이터는 '대여중' 이에요.
하지만 상식적으로 한 차량의 상태가 대여 가능하며 대여중이라는 값이 동시에 존재할 수 없죠.
결국
💡 한 차량의 상태가 단 한 건이라도 제시된 기간에 '대여중'이라면 해당 차량은 대여중으로 표시되어야 함
이라는 결론을 내릴 수 있어요
그러면 Oracle 함수 중 '특정 조건을 만족하는 값의 존재 여부'를 판단하는 EXISTS를 이용할 수 있겠네요 !
문제 풀이
Answer :
SELECT DISTINCT CAR_ID
, CASE WHEN EXISTS (SELECT 1
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY B
WHERE A.CAR_ID = B.CAR_ID
AND TO_DATE('2022-10-16', 'YYYY-MM-DD') BETWEEN START_DATE AND END_DATE)
THEN '대여중'
ELSE '대여 가능'
END AS AVAILABILITY
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY A
ORDER BY CAR_ID DESC;
위 쿼리는 CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블 데이터 중
CASE WHEN EXISTS 구문을 통해 CAR_ID 당 대여 시작일과 대여 종료일 기간 내에 2022년 10월 16일이 단 한 건이라도 포함되는 데이터가 존재한다면 '대여중'값을, 한 건도 없다면 '대여 가능' 값을 반환하도록 구성되어 있어요.
(현재 데이터 수 만으로는 판단이 힘들겠지만) IN을 사용해 모든 값들을 순회하기보다는 EXISTS를 통해 값이 존재한다면 탐색을 종료하는 것이 좀 더 성능 향상할 수 있는 방법이에요
그리고 다른 분들께서는 MAX 함수의 문자열 대소비교를 통해 '대여중'이 '대여ⅴ(띄움표시)가능'보다 크다는 사실을 통해 문제를 해결하셨던데, 만약 요구되는 글자가 '대여중이 아닙니다'와 같이 변경될 경우 결과값이 달라지기 때문에 문제 풀이를 위해서는 괜찮지만 공부를 위해서는 다른 방법들이 더 좋아 보여요🙂
참고: MAX 함수를 통해 문자열 대소비교 ?
SELECT MAX(LITERAL)
FROM (SELECT '대여중' AS LITERAL FROM DUAL
UNION ALL
SELECT '대여 가능' AS LITERAL FROM DUAL);
=========================================
RESULT : 대여중