정답 쿼리
SELECT DISTINCT(C.CAR_ID), C.CAR_TYPE, ROUND(DAILY_FEE * 30 - (DAILY_FEE * 30 * (DISCOUNT_RATE/100))) AS FEE
FROM CAR_RENTAL_COMPANY_CAR C
JOIN CAR_RENTAL_COMPANY_RENTAL_HISTORY H
ON C.CAR_ID = H.CAR_ID
JOIN CAR_RENTAL_COMPANY_DISCOUNT_PLAN P
ON C.CAR_TYPE = P.CAR_TYPE
WHERE C.CAR_TYPE IN ('세단', 'SUV')
AND C.CAR_ID NOT IN (
SELECT CAR_ID
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
WHERE START_DATE BETWEEN '2022-11-01' AND '2022-11-30'
OR END_DATE BETWEEN '2022-11-01' AND '2022-11-30'
OR (START_DATE <= '2022-11-01' AND END_DATE >= '2022-11-30'))
AND DURATION_TYPE = '30일 이상'
AND ROUND(DAILY_FEE * 30 - (DAILY_FEE * 30 * (DISCOUNT_RATE/100))) BETWEEN 500000 AND 2000000
ORDER BY FEE DESC, C.CAR_TYPE, C.CAR_ID DESC;
해설
이 문제는 조건이 많아서 까다로웠지만, 총 5가지 조건으로 쪼개어서 풀이하면 쉽게 풀리는 문제였다.
- 자동차 종류가 '세단' 또는 'SUV' 인 자동차 중
- 2022년 11월 1일부터 2022년 11월 30일까지 대여 가능하고
- 30일간의 대여 금액이 50만원 이상 200만원 미만인 자동차에 대해서
- 자동차 ID, 자동차 종류, 대여 금액(컬럼명: FEE) 리스트를 출력하는 SQL문을 작성해주세요.
- 결과는 대여 금액을 기준으로 내림차순 정렬하고, 대여 금액이 같은 경우 자동차 종류를 기준으로 오름차순 정렬, 자동차 종류까지 같은 경우 자동차 ID를 기준으로 내림차순 정렬해주세요.
이 중 2번 문제에 대한 조건을 설정하는게 가장 까다로웠다. 그럼 가장 까다로웠던 2번 조건부터 하나씩 차근차근 풀이해보겠다.
2. 2022년 11월 1일부터 2022년 11월 30일까지 대여 가능하고
SELECT CAR_ID
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
WHERE START_DATE BETWEEN '2022-11-01' AND '2022-11-30'
OR END_DATE BETWEEN '2022-11-01' AND '2022-11-30'
OR (START_DATE <= '2022-11-01' AND END_DATE >= '2022-11-30'))
대여 기간에 관련된 컬럼은 CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블에 있다. 여기에서 나는 아래 3가지로 다시 쪼개어서 조건을 설정해주었다.
- start_date가 2022년 11월 1일부터 2022년 11월 30일 사이에 있으면 안된다.
- end_date가 2022년 11월 1일부터 2022년 11월 30일 사이에 있으면 안된다.
- start_date가 2022년 11월 1일보다 작고, end_date가 2022년 11월 30일보다 크면 안된다.
이 조건을 주석으로 적어놓고, 그대로 WHERE절을 통해서 조건문을 만들어 주었다. 이 때, 서브쿼리를 이용했는데, WHERE절에서 '안된다'에 해당하는 조건을 걸기 위해 NOT IN을 사용해야했다. 그래서 서브쿼리에는 반대로 '된다'에 해당하는 조건을 넣어주었다. SELECT문에는 식별키인 CAR_ID을 넣어주어서 이 조건에 해당되는 CAR_ID는 전부 제외시키도록 했다.
1. 자동차 종류가 '세단' 또는 'SUV' 인 자동차 중
WHERE C.CAR_TYPE IN ('세단', 'SUV')
AND C.CAR_ID NOT IN (
SELECT CAR_ID
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
WHERE START_DATE BETWEEN '2022-11-01' AND '2022-11-30'
OR END_DATE BETWEEN '2022-11-01' AND '2022-11-30'
OR (START_DATE <= '2022-11-01' AND END_DATE >= '2022-11-30'))
위 조건을 서브쿼리로 만들어주고, 1번 조건과 함께 WHERE절에 AND로 묶어주었다.
3. 30일간의 대여 금액이 50만원 이상 200만원 미만인 자동차에 대해서
WHERE C.CAR_TYPE IN ('세단', 'SUV')
AND C.CAR_ID NOT IN (
SELECT CAR_ID
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
WHERE START_DATE BETWEEN '2022-11-01' AND '2022-11-30'
OR END_DATE BETWEEN '2022-11-01' AND '2022-11-30'
OR (START_DATE <= '2022-11-01' AND END_DATE >= '2022-11-30'))
AND DURATION_TYPE = '30일 이상'
AND ROUND(DAILY_FEE * 30 - (DAILY_FEE * 30 * (DISCOUNT_RATE/100))) BETWEEN 500000 AND 2000000
3번 조건 또한 AND로 WHERE절에 같이 묶어주었다.
4. 자동차 ID, 자동차 종류, 대여 금액(컬럼명: FEE) 리스트를 출력하는 SQL문을 작성해주세요.
SELECT DISTINCT(C.CAR_ID), C.CAR_TYPE, ROUND(DAILY_FEE * 30 - (DAILY_FEE * 30 * (DISCOUNT_RATE/100))) AS FEE
FROM CAR_RENTAL_COMPANY_CAR C
JOIN CAR_RENTAL_COMPANY_RENTAL_HISTORY H
ON C.CAR_ID = H.CAR_ID
JOIN CAR_RENTAL_COMPANY_DISCOUNT_PLAN P
ON C.CAR_TYPE = P.CAR_TYPE
WHERE C.CAR_TYPE IN ('세단', 'SUV')
AND C.CAR_ID NOT IN (
SELECT CAR_ID
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
WHERE START_DATE BETWEEN '2022-11-01' AND '2022-11-30'
OR END_DATE BETWEEN '2022-11-01' AND '2022-11-30'
OR (START_DATE <= '2022-11-01' AND END_DATE >= '2022-11-30'))
AND DURATION_TYPE = '30일 이상'
AND ROUND(DAILY_FEE * 30 - (DAILY_FEE * 30 * (DISCOUNT_RATE/100))) BETWEEN 500000 AND 2000000
join을 통해 3개의 테이블을 모두 묶어주고(결측치가 없어서 inner join을 하든, left join을 하든, right join을 하든 결과는 똑같다.) fee에 대한 리스트를 계산하여 select문에 넣어주었다.(대여금액 * 30일 - 할인 된 금액)
5. 결과는 대여 금액을 기준으로 내림차순 정렬하고, 대여 금액이 같은 경우 자동차 종류를 기준으로 오름차순 정렬, 자동차 종류까지 같은 경우 자동차 ID를 기준으로 내림차순 정렬해주세요.
SELECT DISTINCT(C.CAR_ID), C.CAR_TYPE, ROUND(DAILY_FEE * 30 - (DAILY_FEE * 30 * (DISCOUNT_RATE/100))) AS FEE
FROM CAR_RENTAL_COMPANY_CAR C
JOIN CAR_RENTAL_COMPANY_RENTAL_HISTORY H
ON C.CAR_ID = H.CAR_ID
JOIN CAR_RENTAL_COMPANY_DISCOUNT_PLAN P
ON C.CAR_TYPE = P.CAR_TYPE
WHERE C.CAR_TYPE IN ('세단', 'SUV')
AND C.CAR_ID NOT IN (
SELECT CAR_ID
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
WHERE START_DATE BETWEEN '2022-11-01' AND '2022-11-30'
OR END_DATE BETWEEN '2022-11-01' AND '2022-11-30'
OR (START_DATE <= '2022-11-01' AND END_DATE >= '2022-11-30'))
AND DURATION_TYPE = '30일 이상'
AND ROUND(DAILY_FEE * 30 - (DAILY_FEE * 30 * (DISCOUNT_RATE/100))) BETWEEN 500000 AND 2000000
ORDER BY FEE DESC, C.CAR_TYPE, C.CAR_ID DESC;
마지막으로 정렬해주면 끝난다!
'코딩테스트 > SQL 코테' 카테고리의 다른 글
[solvesql]쇼핑몰의 일일 매출액과 ARPPU (0) | 2024.07.11 |
---|---|
[solvesql] 할부는 몇개월로 해드릴까요 해설 (0) | 2024.07.07 |
[프로그래머스 SQL]조회수가 가장 많은 중고거래 게시판의 첨부파일 조회하기 (0) | 2023.08.08 |
[프로그래머스 SQL] 오랜 기간 보호한 동물(2) (0) | 2023.08.07 |
[프로그래머스 SQL] 대여 횟수가 많은 자동차들의 월별 대여 횟수 구하기 (0) | 2023.08.03 |
댓글