[ํ๋ก๊ทธ๋๋จธ์ค] ์๋์ฐจ ๋์ฌ ๊ธฐ๋ก๋ณ ๋์ฌ ๊ธ์ก ๊ตฌํ๊ธฐ (23.06.14 ์ฌํ์ด)
๐ข ๋ณธ ํฌ์คํ ์ ํ์ฉ๋๋ ๊ธฐ๋ณธ ๋ฌธ์ ๋ฐ ์๋ฃ ์ถ์ฒ๋
ํ๋ก๊ทธ๋๋จธ์ค ์ฝ๋ฉํ
์คํธ ์ฐ์ต,
https://school.programmers.co.kr/learn/challenges?page=1&languages=mysql%2Coracle์์ ๋ฐํ๋๋ค.
โ ๋ฌธ์
๋ฌธ์ ์ค๋ช
๋ค์์ ์ด๋ ์๋์ฐจ ๋์ฌ ํ์ฌ์์ ๋์ฌ ์ค์ธ ์๋์ฐจ๋ค์ ์ ๋ณด๋ฅผ ๋ด์ CAR_RENTAL_COMPANY_CAR ํ ์ด๋ธ๊ณผ ์๋์ฐจ ๋์ฌ ๊ธฐ๋ก ์ ๋ณด๋ฅผ ๋ด์ CAR_RENTAL_COMPANY_RENTAL_HISTORY ํ ์ด๋ธ๊ณผ ์๋์ฐจ ์ข ๋ฅ ๋ณ ๋์ฌ ๊ธฐ๊ฐ ์ข ๋ฅ ๋ณ ํ ์ธ ์ ์ฑ ์ ๋ณด๋ฅผ ๋ด์ CAR_RENTAL_COMPANY_DISCOUNT_PLAN ํ ์ด๋ธ ์ ๋๋ค.
CAR_RENTAL_COMPANY_CAR ํ ์ด๋ธ์ ์๋์ ๊ฐ์ ๊ตฌ์กฐ๋ก ๋์ด์์ผ๋ฉฐ, CAR_ID, CAR_TYPE, DAILY_FEE, OPTIONS ๋ ๊ฐ๊ฐ ์๋์ฐจ ID, ์๋์ฐจ ์ข ๋ฅ, ์ผ์ผ ๋์ฌ ์๊ธ(์), ์๋์ฐจ ์ต์ ๋ฆฌ์คํธ๋ฅผ ๋ํ๋ ๋๋ค.
Column name | Type | Nullable |
CAR_ID | INTEGER | FALSE |
CAR_TYPE | VARCHAR(255) | FALSE |
DAILY_FEE | INTEGER | FALSE |
OPTIONS | VARCHAR(255) | FALSE |
์๋์ฐจ ์ข ๋ฅ๋ '์ธ๋จ', 'SUV', '์นํฉ์ฐจ', 'ํธ๋ญ', '๋ฆฌ๋ฌด์ง' ์ด ์์ต๋๋ค. ์๋์ฐจ ์ต์ ๋ฆฌ์คํธ๋ ์ฝค๋ง(',')๋ก ๊ตฌ๋ถ๋ ํค์๋ ๋ฆฌ์คํธ(์: ''์ด์ ์ํธ,์ค๋งํธํค,์ฃผ์ฐจ๊ฐ์ง์ผ์'')๋ก ๋์ด์์ผ๋ฉฐ, ํค์๋ ์ข ๋ฅ๋ '์ฃผ์ฐจ๊ฐ์ง์ผ์', '์ค๋งํธํค', '๋ค๋น๊ฒ์ด์ ', 'ํตํ์ํธ', '์ด์ ์ํธ', 'ํ๋ฐฉ์นด๋ฉ๋ผ', '๊ฐ์ฃฝ์ํธ' ๊ฐ ์์ต๋๋ค.
CAR_RENTAL_COMPANY_RENTAL_HISTORY ํ ์ด๋ธ์ ์๋์ ๊ฐ์ ๊ตฌ์กฐ๋ก ๋์ด์์ผ๋ฉฐ, HISTORY_ID, CAR_ID, START_DATE, END_DATE ๋ ๊ฐ๊ฐ ์๋์ฐจ ๋์ฌ ๊ธฐ๋ก ID, ์๋์ฐจ ID, ๋์ฌ ์์์ผ, ๋์ฌ ์ข ๋ฃ์ผ์ ๋ํ๋ ๋๋ค.
Column name | Type | Nullable |
HISTORY_ID | INTEGER | FALSE |
CAR_ID | INTEGER | FALSE |
START_DATE | DATE | FALSE |
END_DATE | DATE | FALSE |
CAR_RENTAL_COMPANY_DISCOUNT_PLAN ํ ์ด๋ธ์ ์๋์ ๊ฐ์ ๊ตฌ์กฐ๋ก ๋์ด์์ผ๋ฉฐ, PLAN_ID, CAR_TYPE, DURATION_TYPE, DISCOUNT_RATE ๋ ๊ฐ๊ฐ ์๊ธ ํ ์ธ ์ ์ฑ ID, ์๋์ฐจ ์ข ๋ฅ, ๋์ฌ ๊ธฐ๊ฐ ์ข ๋ฅ, ํ ์ธ์จ(%)์ ๋ํ๋ ๋๋ค.
Column name | Type | Nullable |
PLAN_ID | INTEGER | FALSE |
CAR_TYPE | VARCHAR(255) | FALSE |
DURATION_TYPE | VARCHAR(255) | FALSE |
DISCOUNT_RATE | INTEGER | FALSE |
ํ ์ธ์จ์ด ์ ์ฉ๋๋ ๋์ฌ ๊ธฐ๊ฐ ์ข ๋ฅ๋ก๋ '7์ผ ์ด์' (๋์ฌ ๊ธฐ๊ฐ์ด 7์ผ ์ด์ 30์ผ ๋ฏธ๋ง์ธ ๊ฒฝ์ฐ), '30์ผ ์ด์' (๋์ฌ ๊ธฐ๊ฐ์ด 30์ผ ์ด์ 90์ผ ๋ฏธ๋ง์ธ ๊ฒฝ์ฐ), '90์ผ ์ด์' (๋์ฌ ๊ธฐ๊ฐ์ด 90์ผ ์ด์์ธ ๊ฒฝ์ฐ) ์ด ์์ต๋๋ค. ๋์ฌ ๊ธฐ๊ฐ์ด 7์ผ ๋ฏธ๋ง์ธ ๊ฒฝ์ฐ ํ ์ธ์ ์ฑ ์ด ์์ต๋๋ค.
๋ฌธ์ ์ค๋ช
CAR_RENTAL_COMPANY_CAR ํ ์ด๋ธ๊ณผ CAR_RENTAL_COMPANY_RENTAL_HISTORY ํ ์ด๋ธ๊ณผ CAR_REN TAL_COMPANY_DISCOUNT_PLAN ํ ์ด๋ธ์์ ์๋์ฐจ ์ข ๋ฅ๊ฐ 'ํธ๋ญ'์ธ ์๋์ฐจ์ ๋์ฌ ๊ธฐ๋ก์ ๋ํด์ ๋์ฌ ๊ธฐ๋ก ๋ณ๋ก ๋์ฌ ๊ธ์ก(์ปฌ๋ผ๋ช : FEE)์ ๊ตฌํ์ฌ ๋์ฌ ๊ธฐ๋ก ID์ ๋์ฌ ๊ธ์ก ๋ฆฌ์คํธ๋ฅผ ์ถ๋ ฅํ๋ SQL๋ฌธ์ ์์ฑํด์ฃผ์ธ์. ๊ฒฐ๊ณผ๋ ๋์ฌ ๊ธ์ก์ ๊ธฐ์ค์ผ๋ก ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌํ๊ณ , ๋์ฌ ๊ธ์ก์ด ๊ฐ์ ๊ฒฝ์ฐ ๋์ฌ ๊ธฐ๋ก ID๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌํด์ฃผ์ธ์.
์ฃผ์์ฌํญ
FEE์ ๊ฒฝ์ฐ ์์์ฒ๋ผ ์ ์๋ถ๋ถ๋ง ์ถ๋ ฅ๋์ด์ผ ํฉ๋๋ค.
โ ํ์ด
๋ฌธ์ ์๊ตฌ์ฌํญ
์๋์ฐจ ์ข ๋ฅ๊ฐ 'ํธ๋ญ'์ธ ์๋์ฐจ์ ๋์ฌ ๊ธฐ๋ก์ ๋ํด์ < WHERE์ ์ ์กฐ๊ฑด1 : CAR_TYPE
๋์ฌ ๊ธฐ๋ก ๋ณ๋ก ๋์ฌ ๊ธ์ก(์ปฌ๋ผ๋ช : FEE)์ ๊ตฌํ์ฌ < ๋์ฌ ๊ธฐ๋ก๋ณ๋ก FEE *
๋์ฌ ๊ธฐ๋ก ID์ ๋์ฌ ๊ธ์ก ๋ฆฌ์คํธ๋ฅผ ์ถ๋ ฅ
๊ฒฐ๊ณผ๋ ๋์ฌ ๊ธ์ก์ ๊ธฐ์ค์ผ๋ก ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌ < ์ ๋ ฌ์กฐ๊ฑด1
๋์ฌ ๊ธ์ก์ด ๊ฐ์ ๊ฒฝ์ฐ ๋์ฌ ๊ธฐ๋ก ID๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌ < ์ ๋ ฌ์กฐ๊ฑด2
* ๋ฌธ์ ์ ์ฃผ์ ํ์ด๋ FEE๋ฅผ ๊ตฌํ๋ ๊ฒ.
๋ฌธ์ ์ค๋ช ์ ๋ฐ๋ฅด๋ฉด FEE๋ฅผ ๊ตฌํ๋ ๊ณต์์ ์๋์ ๊ฐ์ด ๋ง๋ค ์ ์๋ค.
FEE = DAILY_FEE × ๋์ฌ๊ธฐ๊ฐ(END_DATE - START_DATE + 1) × ๋์ฌ๊ธฐ๊ฐ๋ณ DISCOUNT_RATE
์ด๋ฒ ํ์ด์์๋ ์๋ ์ฟผ๋ฆฌ๋ก CAR_RENTAL_COMPANY_DISCOUNT_PLAN ์์ ํธ๋ญ์ ๋์ฌ๊ธฐ๊ฐ๋ณ ํ ์ธ์จ์ ์ถ๋ ฅํด์ ํ์ธํด๋ณด๊ณ DISCOUNT_PLAN ํ ์ด๋ธ์ ๋ฐ๋ก ์กฐ์ธํ์ง ์์๋ค.
SELECT DURATION_TYPE, DISCOUNT_RATE
FROM CAR_RENTAL_COMPANY_DISCOUNT_PLAN
WHERE CAR_TYPE = 'ํธ๋ญ';
> ์๋์ฐจ ๋์ฌ ํ์ฌ์์ ๋์ฌ ์ค์ธ ์๋์ฐจ๋ค์ ์ ๋ณด๋ฅผ ๋ด์ CAR_RENTAL_COMPANY_CAR ํ ์ด๋ธ๊ณผ ์๋์ฐจ ๋์ฌ ๊ธฐ๋ก ์ ๋ณด๋ฅผ ๋ด์ CAR_RENTAL_COMPANY_RENTAL_HISTORY ํ ์ด๋ธ์ ์กฐ์ธํด์ค ํ,
DATEDIFF ํจ์๋ก ๋์ฌ๊ธฐ๊ฐ์ ๊ตฌํ๊ณ
CASE๋ฌธ์ผ๋ก ๋์ฌ๊ธฐ๊ฐ๋ณ ํ ์ธ์จ์ ๊ตฌํด์
์ผ์ผ ๋์ฌ๋ฃ(DAILY_FEE) ์ ๊ณฑํด์ HISTORY_ID๋ณ FEE๋ฅผ ์ถ๋ ฅํ๋ค.
FEE์ ์ ์๋ถ๋ถ๋ง ์ถ๋ ฅํ๋ ๊ฒ์ FLOOR๋ฅผ ์ฌ์ฉํด์ฃผ์๋ค.
SELECT RH.HISTORY_ID
,FLOOR((DATEDIFF(RH.END_DATE, RH.START_DATE)+1) * CC.DAILY_FEE *
(CASE WHEN DATEDIFF(RH.END_DATE, RH.START_DATE)+1 >= 90 THEN 0.85
WHEN DATEDIFF(RH.END_DATE, RH.START_DATE)+1 >= 30 THEN 0.92
WHEN DATEDIFF(RH.END_DATE, RH.START_DATE)+1 >= 7 THEN 0.95
ELSE 1 END)) AS FEE
FROM CAR_RENTAL_COMPANY_CAR CC
INNER JOIN CAR_RENTAL_COMPANY_RENTAL_HISTORY RH
ON CC.CAR_ID = RH.CAR_ID
WHERE CC.CAR_TYPE = 'ํธ๋ญ'
ORDER BY 2 DESC, 1 DESC;
โ ์ถ๊ฐ : discount rate๋ฅผ ํ ์ด๋ธ์์ ๊ฐ๊ณ ์์ ์ฌ์ฉํ ์ ์๋๋ก ์ธ๊ฐ์ง ํ ์ด๋ธ ๋ชจ๋ ์กฐ์ธํด์ ํ๋ ๋ฐฉ๋ฒ
โ ์ฒซ๋ฒ์งธ ํ์ด CASE๋ฌธ์์ ๊ฐ ๋์ฌ ๊ธฐ๊ฐ์ ๋ฐ๋ผ ํ ์ธ์จ์ ์ง์ ์ ์ผ๋ก ๋ฃ์ด์ฃผ๋ ๊ฒ์ด ์๋๋ผ CAR_RENTAL_COMPANY_DISCOUNT_PLAN ํ ์ด๋ธ์ DISCOUNT_RATE๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ์กฐ๊ฑด์ ๋ฐ๋ฅธ ์ ๊ฐ์ DURATION_TYPE ์ปฌ๋ผ๊ฐ์ผ๋ก ์ง์ ํ๋ค.
โก CASE๋ฌธ์ผ๋ก ์๋ก ์ค์ ํด์ค DURATION_TYPE ์ปฌ๋ผ์ ๊ธฐ์ค์ผ๋ก DISCOUNT_PLAN ํ ์ด๋ธ๊ณผ ์กฐ์ธํด์ ํ ์ธ์จ์ ๊ณ์ฐํ๋ค.
WITH T1 AS (
SELECT RH.HISTORY_ID AS HISTORY_ID
, DATEDIFF(END_DATE, START_DATE) + 1 AS RENT_PERIOD
, CC.CAR_TYPE AS CAR_TYPE
, CC.DAILY_FEE AS DAILY_FEE
, CASE WHEN DATEDIFF(RH.END_DATE, RH.START_DATE)+1 >= 90 THEN '90์ผ ์ด์'
WHEN DATEDIFF(RH.END_DATE, RH.START_DATE)+1 >= 30 THEN '30์ผ ์ด์'
WHEN DATEDIFF(RH.END_DATE, RH.START_DATE)+1 >= 7 THEN '7์ผ ์ด์'
ELSE 'NONE' END AS DURATION_TYPE
FROM CAR_RENTAL_COMPANY_CAR CC
INNER JOIN CAR_RENTAL_COMPANY_RENTAL_HISTORY RH
ON CC.CAR_ID = RH.CAR_ID
WHERE CC.CAR_TYPE = 'ํธ๋ญ')
SELECT T1.HISTORY_ID AS HISTORY_ID
,FLOOR(T1.DAILY_FEE * T1.RENT_PERIOD * (100-IFNULL(T2.DISCOUNT_RATE,0))/100) AS FEE
FROM T1
LEFT JOIN CAR_RENTAL_COMPANY_DISCOUNT_PLAN T2
ON T1.DURATION_TYPE = T2.DURATION_TYPE
AND T1.CAR_TYPE = T2.CAR_TYPE
ORDER BY 2 DESC, 1 DESC;