<์ค๋์ ํ์ต>
- SQL ๋ผ์ด๋ธ์ธ์ 5ํ์ฐจ (CASE, โญ๏ธ์๋ธ์ฟผ๋ฆฌ, โญ๏ธCTE)
<ํ์ต๋ด์ฉ ์ ๋ฆฌ>
# SQL ๋ผ์ด๋ธ ์ธ์ 5ํ์ฐจ
1. CASE
๋ ๊ฐ์ง ์ผ์ด์ค ํฌ๊ฒ ๋ค๋ฅด์ง ์์. ํ๊ธฐ์ ์ฐจ์ด์ผ ๋ฟ.
else: ์กฐ๊ฑด ์ธ ๋ค๋ฅธ ๋ณ์์ ์ฒ๋ฆฌ ๋ฐฉ์์ ์ง์ ํด์ฃผ๋ ๊ฒ. ์๋ฌ ๋ฐฉ์ง์ ์ค์ํจ!
--(A) ๊ฐ ๋น๊ตํ(Simple CASE)
SELECT
student_id,
student_name,
region,
CASE region
WHEN 'SEOUL' THEN '์์ธ'
WHEN 'BUSAN' THEN '๋ถ์ฐ'
ELSE '๊ธฐํ'
END AS region_kor
FROM basic.students
ORDER BY student_id;
--(B) ์กฐ๊ฑด์ํ(Searched CASE)
SELECT
student_id,
student_name,
region,
CASE
WHEN region = 'SEOUL' THEN '์์ธ'
WHEN region = 'BUSAN' THEN '๋ถ์ฐ'
ELSE '๊ธฐํ'
END AS region_kor
FROM basic.students
ORDER BY student_id;
- case ๋ด / count ๋ก null์ธ ํ ๊ฐ์
--SUM์ผ๋ก Null ๊ฐ์ ์นด์ดํธ
--ํด๋น ์กฐ๊ฑด์ ๋ง์กฑํ๋ null ํ์ 1๋ก ๋ฐํ, ๋ชจ๋ 1์ ๋ํ๋ฉด ํ์ ๊ฐ์
SELECT
COUNT(*)AS total_enrollments,
SUM(CASE WHEN coupon_code IS NOT NULL THEN 1 ELSE 0 END)AS coupon_used_cnt,
SUM(CASE WHEN coupon_code IS NULL THEN 1 ELSE 0 END)AS no_coupon_cnt
FROM basic.enrollments;
--0์ด ๋ฐํ๋ ํ๊น์ง ๋ชจ๋ ์นด์ดํธ, count(*)์ ๋์ผํ ๊ฐ๋ง ๋์ด.
SELECT
COUNT(*)AS total_enrollments,
COUNT(CASE WHEN coupon_code IS NOT NULL THEN 1 ELSE 0 END)AS coupon_used_cnt,
COUNT(CASE WHEN coupon_code IS NULL THEN 1 ELSE 0 END)AS no_coupon_cnt
FROM basic.enrollments;
2. โญ๏ธ์๋ธ์ฟผ๋ฆฌ
:๋ค๋ฅธ SQL ์์ ๋ค์ด์๋ SELECT
https://tjsdud7032.tistory.com/34
[๊ฐ๋ ์ ๋ฆฌ] ์๋ธ์ฟผ๋ฆฌ(Subquery)
๋ค๋ฅธ SQL ์์ ๋ค์ด์๋ SELECTMySQL์ ์๋ธ์ฟผ๋ฆฌ๊ฐ ๋ฐํํ๋ ํํ๊ฐ 4์ข ๋ฅscalar(๊ฐ 1๊ฐ)row(ํ 1๊ฐ)column(์ด 1๊ฐ = ๋ฆฌ์คํธ)table(ํ)Q. ํ๊ท ๋ณด๋ค ๋น์ผ ๊ฐ์ข ์ฐพ๊ธฐ(1. ์๋ธ ์ฟผ๋ฆฌ)๋ชจ๋ ๊ฐ์ข ํ๊ท ๊ตฌํ๊ธฐ (2. ๋ฐ๊นฅ
tjsdud7032.tistory.com
๋ฏธ๋์ค์ต 4) Scalar Subquery; ๊ฐ 1๊ฐ
๋ฌธ์ : enrollments์์ final_price๊ฐ “์ ์ฒด ํ๊ท final_price”๋ณด๋ค ํฐ ์ ์ฒญ๋ง ๋ณด๊ธฐ
์ถ๋ ฅ: enrollment_id, final_price
-- ์ ๋ต
SELECT enrollment_id, final_price
FROM basic.enrollments
WHERE final_price > (
-- ์ ์ฒด ํ๊ท
SELECT avg(final_price)
FROM basic.enrollments
);
๋ฏธ๋์ค์ต 5) Column Subquery; ์ด1๊ฐ, ๋ฆฌ์คํธ
IN()
๋ฌธ์ : level='beginner'์ธ ๊ฐ์ข๋ฅผ ์ ์ฒญํ enrollments๋ง ์ถ๋ ฅ
์ถ๋ ฅ: enrollment_id, course_id
--์ ๋ต
SELECT enrollment_id, course_id
FROM basic.enrollments
where course_id IN (
SELECT course_id
FROM basic.courses
WHERE level = 'beginner'
);
๋ฏธ๋์ค์ต 6) Table Subquery; / ํ
EXISTS / NOT EXISTS
๋ฌธ์ : “๊ฒฐ์ ํ
์ด๋ธ(payments)์ ๊ธฐ๋ก์ด ํ ๋ฒ๋ ์๋ ์ ์ฒญ(enrollment)” ์ฐพ๊ธฐ
์ถ๋ ฅ: enrollment_id
-- ์ ๋ต
SELECT e.enrollment_id
FROM basic.enrollments e
where not exists (
select *
from basic.payments p
where p.enrollment_id=e.enrollment_id
);
๋ฏธ๋์ค์ต 7) FROM ์๋ธ์ฟผ๋ฆฌ(ํ์ ํ ์ด๋ธ)
๋ฌธ์ : ํ์๋ณ ์ ์ฒญ ๊ฑด์(enroll_cnt)๋ฅผ students์ ๋ถ์ฌ์ ์ถ๋ ฅ
์ถ๋ ฅ: student_id, student_name, enroll_cnt (์ ์ฒญ ์์ผ๋ฉด 0)
-- ํ์๋ณ
select s.student_id,
s.student_name,
ifnull(enr.enroll_cnt, 0) as enroll_cnt
from basic.students s
left join
(-- ํ์๋ณ ์ ์ฒญ๊ฑด์
select student_id,
count(enrollment_id) as enroll_cnt
from basic.enrollments
group by student_id
)as enr
on s.student_id=enr.student_id;
๋ฏธ๋์ค์ต 8) CTE (WITH) : ์ด๋ฆ ๋ถ์ธ ํ์ํ ์ด๋ธ
๋ฌธ์ : is_active = 1์ธ ๊ฐ์ข๋ง ๋ฝ๋ CTE(active_courses)๋ฅผ ๋ง๋ค๊ณ , ๊ทธ CTE๋ฅผ ์กฐํํ์ธ์.
์ถ๋ ฅ: course_id, course_name, is_active
with active_course as (
select course_id, course_name, is_active
from basic.courses
where is_active = 1
)
select *
from active_course;
์๋ธ์ฟผ๋ฆฌ์ ์ฉ๋๋ฅผ ์ ์ฒดํฌ!
ํ๋์ ๊ฐ๊ณผ ๋น๊ต = Scalar
์ฌ๋ฌ ๊ฐ๊ณผ ๋น๊ต = Column(IN())
์๋, ์๋ ํ์ธ = Table(exists, not exists)
์ค๊ฐ๊ฒฐ๊ณผ๋ฅผ ๋ง๋ค๊ณ ์ถ์ ๋ = FROM
3. ์ข
ํฉ์ค์ต
ใ
ใ
.. ๋ง์ท๋ค ใ
ใ
ใ
ใ
ใ
ใ
(๊ทผ๋ฐ 40๋ถ ๊ฑธ๋ฆผใ
)
โ
์ต์ข
๋ฏธ์
: “ํ์ ํ ์ค ์์ฝ ๋ฆฌํฌํธ”
์ฐ๋ฆฌ๊ฐ ๋ง๋ค ๊ฒฐ๊ณผ(ํ์ 1๋ช
= 1ํ)
์ถ๋ ฅ:
- `student_id, student_name, region, segment`
- `enroll_cnt` : ์ ์ฒญ ๊ฑด์
- `coupon_used_cnt` : ์ฟ ํฐ ์ด ์ ์ฒญ ๊ฑด์
- `coupon_user_flag` : CASE๋ก ๋ผ๋ฒจ
- coupon_used_cnt = 0 → `no_coupon_user`
- 1 ์ด์ → `coupon_user`
-- ํ์๋ณ ์ ์ฒญ๊ฑด์ enrollments
WITH
enr_by_stu AS (
SELECT student_id,
count(*) AS enroll_cnt
FROM basic.enrollments
GROUP BY student_id
),
-- ํ์๋ณ ์ฟ ํฐ ์ด ์ ์ฒญ ๊ฑด์ enrollments
cp_cnt_per_stu AS (
SELECT student_id,
SUM(CASE WHEN coupon_code IS NULL THEN 0
ELSE 1 end) AS coupon_cnt
FROM basic.enrollments e
GROUP BY student_id
)
-- ์ต์ข
์ถ๋ ฅ
SELECT s.student_id,
s.student_name,
s.region,
s.segment,
IFNULL(e.enroll_cnt, 0) AS enroll_cnt, -- ์ ์ฒญ๊ฑด์
IFNULL(c.coupon_cnt, 0) AS coupon_used_cnt, -- ์ฟ ํฐ ์ฌ์ฉ ์
CASE WHEN c.coupon_cnt = 0 THEN 'no_coupon_user'
ELSE 'coupon_user'
END AS coupon_user_flag
FROM basic.students s
LEFT JOIN enr_by_stu e
ON s.student_id = e.student_id
LEFT JOIN cp_cnt_per_stu c
ON s.student_id = c.student_id
ORDER BY s.student_id;
SQL ๋ฐ์ผ๋ฆฌ ํ์คํธ
# ๊ณผ์
๊ณผ์ 1) CASE๋ก “์ฟ ํฐ ์ฌ์ฉ ์ฌ๋ถ + ๊ฐ๊ฒฉ ๊ตฌ๊ฐ” ๋ผ๋ฒจ ๋ง๋ค๊ธฐ
์ํฉ: ์ด์ํ์ด `enrollments`๋ฅผ ๋ณผ ๋, ์ฟ ํฐ ์ฌ์ฉ ์ฌ๋ถ์ ๊ฒฐ์ ๊ธ์ก ๊ตฌ๊ฐ์ด ํ๋์ ๋ณด์ด๊ธธ ์ํฉ๋๋ค.
๋ชฉํ: `enrollment_status`๊ฐ `active`, `completed`์ธ ์ ์ฒญ๋ง ๋์์ผ๋ก ์๋ ์ปฌ๋ผ์ ์ถ๋ ฅํ์ธ์.
์ถ๋ ฅ ์ปฌ๋ผ
- `enrollment_id`
- `student_id`
- `final_price`
- `coupon_flag`
- ์ฟ ํฐ ๋ฏธ์ฌ์ฉ(`coupon_code IS NULL`) → `'no_coupon'`
- ์ฟ ํฐ ์ฌ์ฉ → `'coupon_used'`
- `price_bucket`
- `final_price < 50000` → `'low'`
- `50000 <= final_price < 90000` → `'mid'`
- `final_price >= 90000` → `'high'`
์ ๋ ฌ
`enrollment_id` ์ค๋ฆ์ฐจ์
-- ๐์ค๋ต
SELECT enrollment_id,
student_id,
final_price,
-- ์ฟ ํฐ ์ฌ์ฉ ์ฌ๋ถ
CASE WHEN coupon_code IS NULL THEN 'no_coupon'
ELSE 'coupon_used'
END AS coupon_flag,
-- price_bucket
CASE WHEN final_price < 50000 THEN 'low'
WHEN 50000 <= final_price < 90000 THEN 'mid'
WHEN final_price >= 90000 THEN 'high'
END price_bucket
FROM basic.enrollments
WHERE enrollment_status IN ('active', 'completed')
ORDER BY enrollment_id ASC;
-- ๐กCASE WHEN ๋->๋ฎ
SELECT enrollment_id,
student_id,
final_price,
-- ์ฟ ํฐ ์ฌ์ฉ ์ฌ๋ถ
CASE WHEN coupon_code IS NULL THEN 'no_coupon'
ELSE 'coupon_used'
END AS coupon_flag,
-- price_bucket
CASE WHEN final_price >= 90000 THEN 'high'
WHEN 50000 <= final_price < 90000 THEN 'mid'
WHEN final_price < 50000 THEN 'low'
END AS price_bucket
FROM basic.enrollments
WHERE enrollment_status IN ('active', 'completed')
ORDER BY enrollment_id ASC;
-- ๐กCASE WHEN 'mid' ๋ถ๋ถ ๋๋ ์ ์ฐ๊ธฐ
SELECT enrollment_id,
student_id,
final_price,
-- ์ฟ ํฐ ์ฌ์ฉ ์ฌ๋ถ
CASE WHEN coupon_code IS NULL THEN 'no_coupon'
ELSE 'coupon_used'
END AS coupon_flag,
-- price_bucket
CASE WHEN final_price < 50000 THEN 'low'
WHEN final_price >= 50000 AND final_price < 90000 THEN 'mid'
WHEN final_price >= 90000 THEN 'high'
END AS price_bucket
FROM basic.enrollments
WHERE enrollment_status IN ('active', 'completed')
ORDER BY enrollment_id ASC;
<์ค๋ต๋ ธํธ>
- CASE WHEN ๋ฒ์์กฐ๊ฑด ์ ์ ๋, ๋ฎ์๊ฒ๋ถํฐ ๋์ ๊ฒ๊น์ง ์ฐ๊ณ ์ค๊ฐ ๋ฒ์๋ฅผ ๋ฌถ์ด์ (1<x<=10) ์ฐ๋ฉด ๊ฐ์ ์ค๋ฅ๊ฐ ๋ ์ ์๋ค.
์? x์ ์กฐ๊ฑด์ ๋งจ์ ์กฐ๊ฑด๋ถํฐ ํ์ ๋, ์ฒซ ์ค ์กฐ๊ฑด์ ๋ง์กฑํ๋ฉด ์๋ ์กฐ๊ฑด์ ๊ฒ์ฌ์กฐ์ฐจ ์ ๋จ.
๋ฐฉ๋ฒ1) ๊ฐ์ด ๋์ ์กฐ๊ฑด์ ๋งจ ์๋ก -> ๋ฎ์ ๊ฐ ์กฐ๊ฑด
๋ฐฉ๋ฒ2) ์ค๊ฐ๋ฒ์ ์กฐ๊ฑด์ ๋ฌถ์ด์ ์ฐ์ง ๋ง๊ณ ๋๋ ์ (WHEN x>1 AND x<=10)
๊ณผ์ 2) IN ์๋ธ์ฟผ๋ฆฌ๋ก “SQL ์นดํ ๊ณ ๋ฆฌ ๊ฐ์ข๋ฅผ ์ ์ฒญํ ํ์” ์ฐพ๊ธฐ
์ํฉ: ๋ง์ผํ
ํ์ด **SQL ์นดํ
๊ณ ๋ฆฌ** ๊ฐ์ข๋ฅผ ์ ์ฒญํ ํ์์๊ฒ๋ง ์๋ด ๋ฉ์์ง๋ฅผ ๋ณด๋ด๋ ค ํฉ๋๋ค.
๋ชฉํ: `courses.category = 'sql'`์ธ ๊ฐ์ข๋ฅผ **ํ ๋ฒ์ด๋ผ๋ ์ ์ฒญํ** ํ์ ๋ชฉ๋ก์ ์ถ๋ ฅํ์ธ์.
(์ ์ฒญ ์ํ๋ `active`, `completed`๋ง ํฌํจ / `cancelled` ์ ์ธ)
์ถ๋ ฅ ์ปฌ๋ผ:
- `student_id`
- `student_name`
์ ๋ ฌ:
- `student_id` ์ค๋ฆ์ฐจ์
-- ๐์ค๋ต / ์ ๊ทผ๋ฐฉ์ ํ๋ ธ์.
SELECT student_id,
student_name
FROM basic.students
WHERE student_id IN (
SELECT e.student_id
FROM basic.enrollments e
WHERE e.enrollment_status IN ('active', 'completed')
)
ORDER BY student_id;
-- ๐ก์กฐ๊ฑด ๋ ๊ฐ join์ผ๋ก ํฉ์น๊ธฐ
SELECT s.student_id, s.student_name
FROM basic.students s
WHERE s.student_id IN (
SELECT e.student_id
FROM basic.enrollments e
LEFT JOIN basic.courses c
ON e.course_id=c.course_id
WHERE c.category = 'sql'
AND e.enrollment_status IN ('active', 'completed')
)
ORDER BY s.student_id ASC;
-- ๐ก๋ต์ง ์ ๋ต
SELECT s.student_id,
s.student_name
FROM basic.students s
WHERE s.student_id IN (
SELECT e.student_id
FROM basic.enrollments e
-- inrollment ์กฐ๊ฑด ๋ฌ๊ธฐ
WHERE e.enrollment_status IN ('active', 'completed')
-- and๋ก ์ถ๊ฐ ์กฐ๊ฑด ๋ฌ๊ธฐ
AND e.course_id IN (
SELECT c.course_id
FROM basic.courses c
WHERE c.category = 'sql'
)
)
ORDER BY s.student_id;
<์ค๋ต๋ ธํธ>
- ์๋ธ์ฟผ๋ฆฌ(IN/EXISTS) ์์๋ ‘ID๋ฅผ ๊ณ ๋ฅด๋ ๋ฐ ํ์ํ ๋ชจ๋ ์กฐ๊ฑด’์ด ๋ค์ด๊ฐ์ผ ํ๋ค.
๋ ์กฐ๊ฑด์ด ๊ฐ๊ฐ ๋ค๋ฅธ ํ ์ด๋ธ์ ์์ผ๋ฉด JOIN ์ฌ์ฉ
courses ์กฐ๊ฑด, enrollments ์กฐ๊ฑด์ join์ผ๋ก ํฉ์นจ
์ด๊ฒ์ WHERE IN() ์๋ธ์ฟผ๋ฆฌ๋ก ์ฌ์ฉ
1๏ธโฃ ๋จผ์ ‘์ด๋ค ID๊ฐ ๋์์ธ์ง’๋ฅผ ์ ์ํ๋ค
2๏ธโฃ ๊ทธ ID๋ฅผ ๋ฐ๊นฅ์์ ์ถ๋ ฅํ๋ค
๊ณผ์ 3) NOT EXISTS๋ก “์ฟ ํฐ์ ํ ๋ฒ๋ ์ฌ์ฉํ์ง ์์ ํ์” ์ฐพ๊ธฐ
์ํฉ
์ฟ ํฐ์ ํ ๋ฒ๋ ์ฌ์ฉํ์ง ์์ ํ์์๊ฒ “์ฒซ ์ฟ ํฐ ํํ”์ ์ฃผ๋ ค๊ณ ํฉ๋๋ค.
๋ชฉํ
์๋ ์กฐ๊ฑด์ ๋ง์กฑํ๋ ํ์๋ง ์ถ๋ ฅํ์ธ์.
- ํด๋น ํ์์ enrollments ์ค์์
- `coupon_code IS NOT NULL`์ธ ํ์ด **๋จ ํ ๊ฑด๋ ์๋ ํ์**
> ํฌ์ธํธ: “์๋ค”๋ฅผ ์ฐพ๋ ๊ฐ์ฅ ๋ํ ํจํด์ด NOT EXISTS ์
๋๋ค.
์ถ๋ ฅ ์ปฌ๋ผ
- `student_id`
- `student_name`
์ ๋ ฌ
- `student_id` ์ค๋ฆ์ฐจ์
-- ์ ๋ต
SELECT s.student_id, s.student_name
FROM basic.students s
WHERE NOT EXISTS (
SELECT *
FROM basic.enrollments e
WHERE e.student_id=s.student_id
AND e.coupon_code IS NOT NULL
)
ORDER BY s.student_id;
๊ณผ์ 4) CTE๋ก “ํ์๋ณ ์ ์ฒญ/์ฟ ํฐ ์์ฝ + ๋ผ๋ฒจ( CASE )” ๋ง๋ค๊ธฐ
์ํฉ
์ด์ํ์ด ํ์๋ณ๋ก “์ ์ฒญ ์ / ์ฟ ํฐ ์ฌ์ฉ ์ / ์ฟ ํฐ ์ ์ ์ฌ๋ถ / ์ ์ฒญ ์ ์ ์ฌ๋ถ”๋ฅผ ํ ๋ฒ์ ๋ณด๊ณ ์ถ์ดํฉ๋๋ค.
๋ชฉํ
CTE 2๊ฐ๋ก ์์ฝ ํ
์ด๋ธ์ ๋ง๋ ๋ค `students`์ LEFT JOINํด์ ์๋๋ฅผ ์ถ๋ ฅํ์ธ์.
๋จ, **์ ์ฒญ ์ํ๋ `active`, `completed`๋ง ํฌํจ** (์ทจ์ ์ ์ธ)
์ถ๋ ฅ ์ปฌ๋ผ
- `student_id`
- `student_name`
- `enroll_cnt` (์ ์ฒญ ์)
- `coupon_used_cnt` (์ฟ ํฐ ์ฌ์ฉ ์ ์ฒญ ์)
- `enroll_flag`
- `enroll_cnt = 0` → `'no_enroll'`
- ๊ทธ ์ธ → `'has_enroll'`
- `coupon_user_flag`
- `coupon_used_cnt = 0` → `'no_coupon_user'`
- ๊ทธ ์ธ → `'coupon_user'`
- `coupon_usage_rate_pct`
- `enroll_cnt = 0`์ด๋ฉด `0`
- ๊ทธ ์ธ `ROUND(coupon_used_cnt / enroll_cnt * 100, 1)`
์ ๋ ฌ
- `student_id` ์ค๋ฆ์ฐจ์
-- ๐์ค๋ต
WITH
-- ์ ์ฒญ ์
enroll_cnt AS ( -- CTE์ ๋ณ์นญ์ ์๋ธ์ฟผ๋ฆฌ์ ๋ค๋ฅด๊ฒ ๋ฐฐ์ ํ๋ ๊ฒ ์ข์.
SELECT e.student_id
, COUNT(*) -- ๋ณ์นญ์ ๊ผญ ์ ์ด์ค์ผ ํจ.
FROM basic.enrollments e
WHERE e.enrollment_status IN ('active', 'completed')
GROUP BY e.student_id
)
-- ์ฟ ํฐ ์ฌ์ฉ ์
cp_cnt AS (
SELECT e.student_id
, SUM(CASE WHEN e.coupon_code IS NOT NULL THEN 1 ELSE 0 END)AS coupon_cnt
FROM basic.enrollments e
GROUP BY e.student_id
)
-- ์ต์ข
์ถ๋ ฅ(ํ์๋ณ)
SELECT s.student_id
, s.student_name
, enroll_cnt
, ifnull(e.enroll_cnt, 0) AS enroll_cnt
, ifnull(c.coupon_cnt, 0) AS coupon_cnt
-- enroll_flag
, CASE WHEN enroll_cnt=0 THEN 'no_enroll' -- select์์ ์ฌ์ฉํ ๋ณ์นญ์ select ๋ด์์ ์ฌ์ฌ์ฉ ๋ถ๊ฐ!!!
ELSE 'has_enroll'
END enroll_flag
-- coupon_user_flag
, CASE WHEN ifnull(c.coupon_cnt, 0)=0 THEN 'no_coupon_user'
ELSE 'coupon_user'
END coupon_user_flag
-- coupon_usage_rate_pct -- ๋ถ๋ชจ๊ฐ 0์ผ ๋ ์ค๋ฅ ๋ฐ์ ๊ฐ๋ฅ์ฑ ์์. ๋ถ๋ชจ๊ฐ 0์ผ ๋๋ ๊ทธ๋ฅ 0์ ๋ฐํํ๋๋ก.
FROM basic.students s
LEFT JOIN enroll_cnt e
ON s.student_id=e.student_id
-- ๐กํด์ค
WITH
-- ์ ์ฒญ ์
enr_cnt AS (
SELECT e.student_id
, COUNT(*) AS enroll_cnt
FROM basic.enrollments e
WHERE e.enrollment_status IN ('active', 'completed')
GROUP BY e.student_id
),
-- ์ฟ ํฐ ์ฌ์ฉ ์
cp_cnt AS (
SELECT e.student_id
, SUM(CASE WHEN e.coupon_code IS NOT NULL THEN 1 ELSE 0 END)AS coupon_cnt
FROM basic.enrollments e
GROUP BY e.student_id
)
-- ์ต์ข
์ถ๋ ฅ(ํ์๋ณ)
SELECT s.student_id
, s.student_name
, ifnull(e.enroll_cnt, 0) AS enroll_cnt
, ifnull(c.coupon_cnt, 0) AS coupon_cnt
-- enroll_flag
, CASE WHEN ifnull(e.enroll_cnt, 0)=0 THEN 'no_enroll'
ELSE 'has_enroll'
END enroll_flag
-- coupon_user_flag
, CASE WHEN ifnull(c.coupon_cnt, 0)=0 THEN 'no_coupon_user'
ELSE 'coupon_user'
END coupon_user_flag
-- coupon_usage_rate_pct
, CASE WHEN ifnull(e.enroll_cnt, 0)=0 THEN 0
ELSE round(ifnull(c.coupon_cnt, 0)/ifnull(e.enroll_cnt, 0)*100, 1)
END AS coupon_usage_rate_pct
FROM basic.students s
LEFT JOIN enr_cnt e
ON s.student_id=e.student_id
LEFT JOIN cp_cnt c
ON s.student_id=c.student_id
ORDER BY student_id ASC;
<์ค๋ต๋ ธํธ>
- SELECT ๋ด ๋ณ์นญ์ SELECT์์ ์ฌ์ฌ์ฉ ๋ถ๊ฐ๋ฅ
CASE WHEN ifnull(e.enroll_cnt, 0)=0 THEN 0
ELSE ROUND(ifnull(c.coupon_cnt, 0) / ifnull(e.enroll_cnt, 0) * 100, 1) END AS coupon_usage_rate_pct
- ๋๋๊ธฐ์ ๋ถ๋ชจ๊ฐ 0์ด๋ฉด ๊ณ์ฐ ๋ถ๊ฐ → ์ค๋ฅ
- ๋ถ๋ชจ๊ฐ 0์ด๋ฉด ๊ทธ๋๋ก 0์ ๋ฐํํ๋๋ก ํจ โถ ๊ณ์ฐ ์์ฒด๋ฅผ ๊ฑด๋๋.
- ELSE: ๋ถ๋ชจ๊ฐ 0์ด ์๋ ๋ชจ๋ ๊ฒฝ์ฐ๋ ์ด๋ ๊ฒ ๊ณ์ฐํด๋ผ.
WITH coupon_by_student AS (
SELECT student_id,
COUNT(*) AS coupon_used_cnt
FROM basic.enrollments
WHERE enrollment_status IN ('active', 'completed')
AND coupon_code IS NOT NULL
GROUP BY student_id
)
- coupon_code๊ฐ NULL์ธ ๊ฒ์ ์ ์ธํ ๊ฐ์๋ฅผ ์ธ์ผํ ๋ SUM๋ ๊ฐ๋ฅํ์ง๋ง,
์ ์ด์ WHERE์์ ๊ฑฐ๋ฅด๋ ๊ฒ ๋ ๊ฐ๋จ!!
# ํ์คํธ
Q1. CTE(WITH)์ ๋ํ ์ค๋ช
์ผ๋ก ๊ฐ์ฅ ์ฌ๋ฐ๋ฅธ ๊ฒ์?
A. CTE๋ ์คํํ๋ฉด DB์ ์๊ตฌ ํ
์ด๋ธ๋ก ์ ์ฅ๋๋ค
B. CTE๋ ๋จ์ผ statement ๋ฒ์์์๋ง ์กด์ฌํ๋ฉฐ, ๊ทธ statement ์์์ ์ฌ๋ฌ ๋ฒ ์ฐธ์กฐํ ์ ์๋ค
C. CTE๋ GROUP BY๊ฐ ๋ฐ๋์ ํฌํจ๋์ด์ผ ํ๋ค
D. CTE๋ MySQL์์ ์ง์๋์ง ์๋๋ค
Q2. MySQL์์ ์๋์ฒ๋ผ FROM ์ ์ ์๋ธ์ฟผ๋ฆฌ๋ฅผ ๋ฃ์ ๋ ๋ฐ๋์ ํ์ํ ๊ฒ์?
SELECT *
FROM (SELECT course_id FROM basic.courses);
A. WHERE ์
B. ORDER BY ์
C. ํ์ ํ
์ด๋ธ(derived table)์ ๋ณ์นญ(alias)
D. LIMIT ์
Q3. `EXISTS` ์๋ธ์ฟผ๋ฆฌ์ ๋ํ ์ค๋ช
์ผ๋ก ์ฌ๋ฐ๋ฅธ ๊ฒ์?
A. ์๋ธ์ฟผ๋ฆฌ๊ฐ 0ํ์ ๋ฐํํ๋ฉด EXISTS๋ TRUE์ด๋ค
B. ์๋ธ์ฟผ๋ฆฌ๊ฐ 1ํ ์ด์์ ๋ฐํํ๋ฉด EXISTS๋ TRUE์ด๋ค
C. EXISTS๋ ์๋ธ์ฟผ๋ฆฌ์ SELECT ์ปฌ๋ผ ๋ชฉ๋ก์ ๋ฐ๋์ ์ค์ ๋ก ์ฌ์ฉํด์ ๊ณ์ฐํ๋ค
D. EXISTS๋ ๋ฐ๋์ GROUP BY์ ํจ๊ป ์จ์ผ ํ๋ค
Q4. `CASE WHEN`(CASE ํํ์) ๋์์ ๋ํ ์ค๋ช
์ผ๋ก ๊ฐ์ฅ ์ฌ๋ฐ๋ฅธ ๊ฒ์?
A. ๋ชจ๋ WHEN ์กฐ๊ฑด์ ๋๊น์ง ํ๊ฐํ ๋ค, TRUE์ธ THEN ๊ฒฐ๊ณผ๋ฅผ ๋ชจ๋ ํฉ์ณ ๋ฐํํ๋ค
B. ์์์๋ถํฐ ์กฐ๊ฑด์ ํ๊ฐํ๋ฉฐ **์ฒ์ TRUE๊ฐ ๋ THEN์ ๊ฐ**์ ๋ฐํํ๊ณ , ELSE๊ฐ ์๊ณ ์กฐ๊ฑด์ด ๋ชจ๋ FALSE๋ฉด NULL์ ๋ฐํํ ์ ์๋ค
C. CASE๋ WHERE ์ ์์๋ง ์ฌ์ฉํ ์ ์๋ค
D. CASE๋ ์ซ์ ๊ฒฐ๊ณผ๋ง ๋ฐํํ ์ ์๋ค
Q5. `IFNULL(expr1, expr2)`์ ๋์์ผ๋ก ์ฌ๋ฐ๋ฅธ ๊ฒ์?
A. expr1์ด NULL์ด๋ฉด expr1์ ๋ฐํํ๋ค
B. IFNULL์ ์ธ์๋ฅผ 3๊ฐ ์ด์ ๋ฐ์ ์ ์๋ค
C. expr1์ด NULL์ด ์๋๋ฉด expr1์, NULL์ด๋ฉด expr2๋ฅผ ๋ฐํํ๋ค
D. IFNULL์ NULL ๊ฐ์ ๋ค๋ฅธ ๊ฐ์ผ๋ก ๋์ฒดํ ์ ์๋ค
# ์๊ธฐ์ฃผ๋ํ์ต์ ์ํ AIํ์ฉ๋ฒ ์ธ์ 1ํ์ฐจ
๊ทธ๋ ๋ค๋ฉด ์์ผ๋ก ์ค์ํ ๊ฒ์ด ๋ฌด์์ผ๊น?
1. ๊ฒฐ๊ณผ๋ฅผ ๊ฒ์ฆํด ๋ผ ์ ์์ด์ผ ํ๋ค.

<๋ด์ผ์ ํ์ต>
- ๋ผ์ด๋ธ ์ธ์
- SQL ๋ผ์ด๋ธ์ธ์ 6ํ์ฐจ
- ์๊ธฐ์ฃผ๋ํ์ต์ ์ํ AIํ์ฉ๋ฒ 2ํ์ฐจ
- ๊ฐ์ธํ์ต
- SQL ์ฝ๋์นดํ 30์ผ, 31์ผ ๋ถ๋
- ํ ์ํฐํด: ๋ฐ์ดํฐ ๋ถ์๊ฐ๊ฐ ๊ฐ์ถฐ์ผํ 9๊ฐ์ง ์ญ๋
- Sub_์ฌ์บ SQL ๋ฌ๋ฆฌ๊ธฐ๋ฐ ๋ฌธ์ ํ์ด (4๋ฒ~)
'์คํ๋ฅดํ ๋ด์ผ๋ฐฐ์์บ ํ(25.12.01~)' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [SQL ์ฝ๋์นดํ] ๋ ๋ฒจ 1 / 1~10 (0) | 2025.12.31 |
|---|---|
| [๊ฐ๋ ์ ๋ฆฌ] ์๋ธ์ฟผ๋ฆฌ(Subquery) (0) | 2025.12.31 |
| [๊ฐ๋ ์ ๋ฆฌ] Having + Subquery (0) | 2025.12.29 |
| ์คํ๋ฅดํ ๋ด์ผ๋ฐฐ์์บ ํ_๋ณธ์บ ํ_data11๊ธฐ ๊น์ ์_TIL_Day 5 (0) | 2025.12.29 |
| SQL ๊ฑท๊ธฐ๋ฐ ๋ฌธ์ ํตํฉ (1) | 2025.12.27 |