프로그래머스 SQL - 59번. (CASE, SUBQUERY, (MAX))

yeyeyeyeye·2025년 3월 7일

문제: CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블에서 2022년 10월 16일에 대여 중인 자동차인 경우 '대여중' 이라고 표시하고, 대여 중이지 않은 자동차인 경우 '대여 가능'을 표시하는 컬럼(컬럼명: AVAILABILITY)을 추가하여 자동차 ID와 AVAILABILITY 리스트를 출력하는 SQL문을 작성해주세요. 이때 반납 날짜가 2022년 10월 16일인 경우에도 '대여중'으로 표시해주시고 결과는 자동차 ID를 기준으로 내림차순 정렬해주세요.

조건 1) 2022년 10월 16일에 대여 중인 자동차인 경우 '대여중' 이라고 표시하고, 대여 중이지 않은 자동차인 경우 '대여 가능'을 표시. 컬럼명(availability)
조건2)이때 반납 날짜가 2022년 10월 16일인 경우에도 '대여중'으로 표시
조건3)자동차 ID를 기준으로 내림차순 정렬

처음에 접근했던 방식

SELECT car_id,
       CASE WHEN '2022-10-16' BETWEEN start_date AND end_date THEN '대여중'
            ELSE '대여 가능' 
       		END AS AVAILABILITY
FROM car_rental_company_rental_history
ORDER BY car_id DESC;

문제점❌:

  1. 같은 car_id가 여러 개 있을 경우 오판할 수 있음.
  • car_id가 같은 차가 여러 번 대여된 경우, 일부는 '대여중'이고 일부는 '대여 가능'일 수도 있다. 1번 풀이는 이런 문제점을 해결한 풀이.

1. 서브쿼리를 활용한 풀이

SELECT DISTINCT car_id,
	   CASE 
       		WHEN car_id IN #IN이 필요한 이유: IN을 사용하면 현재 car_id가 이 목록 안에 있는지 쉽게 확인 가능 
       			(
       			 SELECT DISTINCT car_id
       			 FROM car_rental_company_rental_history
       			 WHERE '2022-10-16' BETWEEN start_date AND end_date
       			) #subquery: '2022-10-16'에 대여중인 자동차 id 목록을 반환
            THEN '대여중'
       		ELSE '대여 가능'
       END AS AVAILABILITY
FROM car_rental_company_rental_history
ORDER BY car_id desc;

2. MAX를 활용한 풀이

SELECT car_id,
       CASE 
           WHEN MAX('2022-10-16' BETWEEN start_date AND end_date) = 1 THEN '대여중'
           ELSE '대여 가능' 
       END AS AVAILABILITY
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
GROUP BY car_id
ORDER BY car_id DESC;

💡동작 원리
car_id별로 모든 대여 기록을 검사한 후, MAX()를 이용해 "대여중" 상태인지 판단하는 방식이다.

  1. 개별 대여 기록에서 "대여중"인지 확인
  • '2022-10-16' BETWEEN start_date AND end_date
    TRUE1, FALSE0으로 변환됨.
    즉, 각 행마다 '2022-10-16'이 대여 기간 내에 포함되면 1, 아니면 0
  1. 같은 car_id내에서 가장 큰 값(MAX())을 구함
  • 같은 car_id의 여러 개 대여 기록 중
  • 하나라도 1이 있으면 MAX()1을 반환
  • 전부 0이면 MAX()0을 반환
  1. CASE문을 통해 최종 상태 결정
  • MAX(...)=1이면 '대여중'
  • 그렇지 않으면 '대여가능'

❌처음에 접근했던 코드의 경우

  • car_id가 중복되어 여러 행이 나올 수 있다.
  • GROUP BY car_id가 없어서, 같은 car_id가 여러 개의 대여 기록을 가질 경우 어떤 행에서는 '대여중', 어떤 행에서는 '대여 가능'으로 나올 수 있다.
    이러면 같은 car_id가 여러 줄로 나오거나, 잘못된 결과를 만들 수도 있다.

✅MAX()를 사용한 버전의 장점

  • 같은 car_id를 가진 여러 개의 대여 기록을 하나로 합침 (GROUP BY car_id)
  • 하나라도 "대여중"이면 MAX()1을 반환하여 '대여중'으로 표시
  • GROUP BY 덕분에 car_id별로 하나의 결과만 나옴

MAX()가 여기서 쓰이는 이유

✏️MAX()는 숫자뿐만 아니라 논리값(0(FALSE) or 1(TRUE))에도 적용 가능!

MAX(2022-10-16BETWEEN start_date AND end_date)

이 부분을 보면 '2022-10-16' BETWEEN start_date AND end_date는 논리값(TRUE 또는 FALSE)을 반환한다.

MAX()가 "최대값"을 찾는 함수라서 쓴 게 아니라,
👉 "하나라도 '대여중'이면 '대여중'으로 판정"하는 로직을 만들기 위해 사용한 셈이다

profile
안녕하세요? 데이터분석가 되고 싶어요.

0개의 댓글