WHERE/FROM/SELECT์ , CTE


๐ก ๋ณต์กํ ๋ฌธ์ ๋ฅผ ๋จ๊ณ๋ณ๋ก ํด๊ฒฐํ๋ ์๋ธ์ฟผ๋ฆฌ๋ฅผ ์๋ฒฝ ์ ๋ฆฌํ๋ค.
์ฟผ๋ฆฌ ์์ ๋ค์ด๊ฐ๋ ๋ ๋ค๋ฅธ ์ฟผ๋ฆฌ.
๋ณต์กํ ์ง๋ฌธ์ ๋จ๊ณ๋ณ๋ก ๋๋ ์ ํด๊ฒฐํ ์ ์๋ค.
-- "ํ๊ท ๋ณด๋ค ๋ง์ด ์ฃผ๋ฌธํ ์ ์ ๋?"
SELECT * FROM orders
WHERE amount > (SELECT AVG(amount) FROM orders);
โโโโโโโโโโโ ์๋ธ์ฟผ๋ฆฌ โโโโโโโโโโโ
[users]
| user_id | name | created_at |
|---------|------|------------|
| 1 | ๊น์ฒ ์ | 2024-01-01 |
| 2 | ์ด์ํฌ | 2024-01-15 |
| 3 | ๋ฐ๋ฏผ์ | 2024-02-01 |
[orders]
| order_id | user_id | amount | order_date |
|----------|---------|--------|------------|
| 101 | 1 | 150000 | 2024-01-10 |
| 102 | 1 | 50000 | 2024-01-20 |
| 103 | 2 | 200000 | 2024-02-05 |
| 104 | 2 | 80000 | 2024-02-10 |
| 105 | 3 | 300000 | 2024-02-15 |
์๋ธ์ฟผ๋ฆฌ๋ ์ด๋์ ์์นํ๋๋์ ๋ฐ๋ผ ๋ค๋ฅด๊ฒ ๋์ํ๋ค.
SELECT (์๋ธ์ฟผ๋ฆฌ) โ ์ค์นผ๋ผ ์๋ธ์ฟผ๋ฆฌ
FROM (์๋ธ์ฟผ๋ฆฌ) โ ์ธ๋ผ์ธ ๋ทฐ
WHERE (์๋ธ์ฟผ๋ฆฌ) โ ์ค์ฒฉ ์๋ธ์ฟผ๋ฆฌ
-- ํ๊ท ์ฃผ๋ฌธ๊ธ์ก๋ณด๋ค ํฐ ์ฃผ๋ฌธ ์กฐํ
SELECT *
FROM orders
WHERE amount > (SELECT AVG(amount) FROM orders);
์๋ธ์ฟผ๋ฆฌ๊ฐ ํ๋์ ๊ฐ(156,000)์ ๋ฐํ โ ๋น๊ต ๊ฐ๋ฅ
-- ์ฃผ๋ฌธํ ์ ์๋ ์ ์ ์กฐํ
SELECT *
FROM users
WHERE user_id IN (SELECT DISTINCT user_id FROM orders);
์๋ธ์ฟผ๋ฆฌ๊ฐ ์ฌ๋ฌ ๊ฐ(1, 2, 3)์ ๋ฐํ โ IN์ผ๋ก ๋น๊ต
-- ์ฃผ๋ฌธํ ์ ์๋ ์ ์ ์กฐํ
SELECT *
FROM users
WHERE user_id NOT IN (SELECT DISTINCT user_id FROM orders);
์๋ธ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์์ ํ ์ด๋ธ์ฒ๋ผ ์ฌ์ฉ.
-- ์ ์ ๋ณ ์ด ์ฃผ๋ฌธ๊ธ์ก ๊ตฌํ ๋ค, 100,000์ ์ด์๋ง ํํฐ
SELECT *
FROM (
SELECT
user_id,
SUM(amount) AS total_amount
FROM orders
GROUP BY user_id
) AS user_totals -- ๋ณ์นญ ํ์!
WHERE total_amount >= 100000;
| user_id | total_amount |
|---|---|
| 1 | 200000 |
| 2 | 280000 |
| 3 | 300000 |
ํฌ์ธํธ: FROM ์ ์๋ธ์ฟผ๋ฆฌ๋ ๋ณ์นญ(AS) ํ์!
๊ฐ ํ๋ง๋ค ์๋ธ์ฟผ๋ฆฌ๊ฐ ์คํ๋์ด ํ๋์ ๊ฐ์ ๋ฐํ.
-- ๊ฐ ์ฃผ๋ฌธ์ ์ ์ฒด ํ๊ท ๊ธ์ก ํจ๊ป ํ์
SELECT
order_id,
amount,
(SELECT AVG(amount) FROM orders) AS avg_amount
FROM orders;
| order_id | amount | avg_amount |
|---|---|---|
| 101 | 150000 | 156000 |
| 102 | 50000 | 156000 |
| 103 | 200000 | 156000 |
| ... | ... | ... |
-- ๊ฐ ์ ์ ์ ์ฃผ๋ฌธ ๊ฑด์๋ฅผ ํจ๊ป ํ์
SELECT
u.user_id,
u.name,
(SELECT COUNT(*)
FROM orders o
WHERE o.user_id = u.user_id) AS order_count
FROM users u;
| user_id | name | order_count |
|---|---|---|
| 1 | ๊น์ฒ ์ | 2 |
| 2 | ์ด์ํฌ | 2 |
| 3 | ๋ฐ๋ฏผ์ | 1 |
์๋ธ์ฟผ๋ฆฌ๊ฐ ๋ ๋ฆฝ์ ์ผ๋ก ์คํ๋จ. ํ ๋ฒ๋ง ์คํ.
-- ์๋ธ์ฟผ๋ฆฌ๊ฐ ๋ฉ์ธ์ฟผ๋ฆฌ์ ๋ฌด๊ด
SELECT * FROM orders
WHERE amount > (SELECT AVG(amount) FROM orders);
์๋ธ์ฟผ๋ฆฌ๊ฐ ๋ฉ์ธ์ฟผ๋ฆฌ์ ๊ฐ์ ์ฐธ์กฐ. ํ๋ง๋ค ์คํ.
-- ์๋ธ์ฟผ๋ฆฌ๊ฐ ๋ฉ์ธ์ฟผ๋ฆฌ์ user_id๋ฅผ ์ฐธ์กฐ
SELECT * FROM orders o1
WHERE amount > (
SELECT AVG(amount)
FROM orders o2
WHERE o2.user_id = o1.user_id -- ๋ฉ์ธ์ฟผ๋ฆฌ ์ฐธ์กฐ!
);
โ "์๊ธฐ ์ ์ ์ ํ๊ท ๋ณด๋ค ํฐ ์ฃผ๋ฌธ"
์๋ธ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๊ฐ ์กด์ฌํ๋์ง ํ์ธ (True/False)
-- ์ฃผ๋ฌธ์ด ์๋ ์ ์ ๋ง ์กฐํ
SELECT *
FROM users u
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.user_id = u.user_id
);
-- ์ฃผ๋ฌธ์ด ์๋ ์ ์ ์กฐํ
SELECT *
FROM users u
WHERE NOT EXISTS (
SELECT 1
FROM orders o
WHERE o.user_id = u.user_id
);
| ์ํฉ | ์ถ์ฒ |
|---|---|
| ์๋ธ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๊ฐ ์์ ๋ | IN |
| ์๋ธ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๊ฐ ํด ๋ | EXISTS |
| NULL ์ฒ๋ฆฌ ํ์ํ ๋ | EXISTS |
-- ๊ฐ์ฅ ํฐ ์ฃผ๋ฌธ ์ฐพ๊ธฐ
SELECT *
FROM orders
WHERE amount = (SELECT MAX(amount) FROM orders);
-- ์ ์ ๋ณ ๊ฐ์ฅ ํฐ ์ฃผ๋ฌธ ์ฐพ๊ธฐ
SELECT *
FROM orders o1
WHERE amount = (
SELECT MAX(amount)
FROM orders o2
WHERE o2.user_id = o1.user_id
);
-- ์ฃผ๋ฌธ ๊ธ์ก ์์ 3๊ฐ
SELECT *
FROM orders
WHERE amount >= (
SELECT MIN(amount)
FROM (
SELECT amount
FROM orders
ORDER BY amount DESC
LIMIT 3
) AS top3
);
-- ์ง์ ์ฃผ๋ฌธ๋ณด๋ค ๊ธ์ก์ด ํฐ ์ฃผ๋ฌธ ์ฐพ๊ธฐ
SELECT *
FROM orders o1
WHERE amount > (
SELECT amount
FROM orders o2
WHERE o2.order_id = o1.order_id - 1
);
โ ์๋์ฐ ํจ์(LAG)๋ก ๋ ์ฝ๊ฒ ๊ฐ๋ฅ!
CTE (Common Table Expression): ์๋ธ์ฟผ๋ฆฌ์ ์ด๋ฆ์ ๋ถ์ฌ ์ฌ์ฌ์ฉ
-- ์๋ธ์ฟผ๋ฆฌ ๋ฐฉ์
SELECT *
FROM (
SELECT user_id, SUM(amount) AS total
FROM orders
GROUP BY user_id
) AS user_totals
WHERE total > 100000;
-- CTE ๋ฐฉ์ (๋ ๊น๋!)
WITH user_totals AS (
SELECT user_id, SUM(amount) AS total
FROM orders
GROUP BY user_id
)
SELECT *
FROM user_totals
WHERE total > 100000;
WITH
user_orders AS (
SELECT user_id, COUNT(*) AS cnt, SUM(amount) AS total
FROM orders
GROUP BY user_id
),
vip_users AS (
SELECT user_id
FROM user_orders
WHERE total >= 200000
)
SELECT u.name, uo.cnt, uo.total
FROM users u
JOIN user_orders uo ON u.user_id = uo.user_id
WHERE u.user_id IN (SELECT user_id FROM vip_users);
์ ๋ต ๋ณด๊ธฐ์ ์ฒด ํ๊ท ์ฃผ๋ฌธ๊ธ์ก๋ณด๋ค ํฐ ์ฃผ๋ฌธ์ order_id, amount๋ฅผ ๊ตฌํ์ธ์.
SELECT order_id, amount
FROM orders
WHERE amount > (SELECT AVG(amount) FROM orders);
์ ๋ต ๋ณด๊ธฐ2024๋ 2์์ ์ฃผ๋ฌธํ ์ ์ ์ ์ด๋ฆ์ ๊ตฌํ์ธ์.
SELECT name
FROM users
WHERE user_id IN (
SELECT DISTINCT user_id
FROM orders
WHERE order_date >= '2024-02-01'
AND order_date < '2024-03-01'
);
์ ๋ต ๋ณด๊ธฐ์ฃผ๋ฌธ์ ํ ๋ฒ๋ ํ์ง ์์ ์ ์ ๋ฅผ ๊ตฌํ์ธ์.
SELECT *
FROM users u
WHERE NOT EXISTS (
SELECT 1
FROM orders o
WHERE o.user_id = u.user_id
);
๋๋:
SELECT *
FROM users
WHERE user_id NOT IN (SELECT DISTINCT user_id FROM orders);
์ ๋ต ๋ณด๊ธฐ๊ฐ ์ ์ ์ ํ๊ท ์ฃผ๋ฌธ๊ธ์ก๋ณด๋ค ํฐ ์ฃผ๋ฌธ์ ์ฐพ์ผ์ธ์.
SELECT *
FROM orders o1
WHERE amount > (
SELECT AVG(amount)
FROM orders o2
WHERE o2.user_id = o1.user_id
);
์ ๋ต ๋ณด๊ธฐ์ด ์ฃผ๋ฌธ๊ธ์ก ๊ธฐ์ค ์์ 2๋ช ์ ์ ์ ์ด๋ฆ๊ณผ ์ด์ก์ ๊ตฌํ์ธ์.
WITH user_totals AS (
SELECT
user_id,
SUM(amount) AS total_amount
FROM orders
GROUP BY user_id
ORDER BY total_amount DESC
LIMIT 2
)
SELECT u.name, ut.total_amount
FROM user_totals ut
JOIN users u ON ut.user_id = u.user_id;
| ์ํฉ | ์ถ์ฒ |
|---|---|
| ๋จ์ ํํฐ๋ง | ์๋ธ์ฟผ๋ฆฌ |
| ์ฌ๋ฌ ํ ์ด๋ธ ๋ฐ์ดํฐ ์กฐํฉ | JOIN |
| ๋ณต์กํ ๋จ๊ณ๋ณ ์ฒ๋ฆฌ | CTE |
| ๊ฐ์ ๊ฒฐ๊ณผ ์ฌ๋ฌ ๋ฒ ์ฌ์ฉ | CTE |
์ฑ๋ฅ ํ:
[์๋ธ์ฟผ๋ฆฌ ์์น]
WHERE์ : ํํฐ๋ง ์กฐ๊ฑด์ผ๋ก ์ฌ์ฉ
FROM์ : ์์ ํ
์ด๋ธ์ฒ๋ผ ์ฌ์ฉ (์ธ๋ผ์ธ ๋ทฐ)
SELECT์ : ๊ฐ ํ์ ๊ฐ ์ถ๊ฐ (์ค์นผ๋ผ)
[์ฃผ์ ์ฐ์ฐ์]
IN / NOT IN: ์ฌ๋ฌ ๊ฐ๊ณผ ๋น๊ต
EXISTS / NOT EXISTS: ์กด์ฌ ์ฌ๋ถ ํ์ธ
๋น๊ต์ฐ์ฐ์: ๋จ์ผ ๊ฐ๊ณผ ๋น๊ต
[CTE]
WITH ์ ๋ก ์๋ธ์ฟผ๋ฆฌ์ ์ด๋ฆ ๋ถ์ฌ ์ฌ์ฌ์ฉ
๊ฐ๋
์ฑ๊ณผ ์ ์ง๋ณด์์ ์ข์
[SQL ์๋ฆฌ์ฆ #4] ์๋์ฐ ํจ์ โ ROW_NUMBER, RANK, LAG์ ๋ง๋ฒ
๐ ์๋ธ์ฟผ๋ฆฌ๋ ๋ณต์กํ ๋ฌธ์ ๋ฅผ ๋จ๊ณ๋ณ๋ก ํด๊ฒฐํ๋ ๋๊ตฌ๋ค.
CTE๋ฅผ ํ์ฉํ๋ฉด ๋ ๊น๋ํ๊ณ ์ฝ๊ธฐ ์ข์ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ์ ์๋ค!