-
CTE(Common Table Expression) ์๋ฒฝ ์ดํด ๊ฐ์ด๋Programing Language/SQL 2025. 6. 13. 22:45๋ฐ์ํ
๐ฏ CTE๋?
**CTE (Common Table Expression)**๋ **"์์ ํ ์ด๋ธ"**์ ๋ง๋๋ SQL ๋ฌธ๋ฒ์ ๋๋ค.
์ฌ์ด ๋น์
- ์๋ธ์ฟผ๋ฆฌ์ ์ ๊ทธ๋ ์ด๋ ๋ฒ์
- ๋ณ์์ฒ๋ผ ์ค๊ฐ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ๊ณ ์ฌ์ฌ์ฉ
- ํจ์์ฒ๋ผ ๋ณต์กํ ๋ก์ง์ ๋จ์ํ
๐ ๊ธฐ๋ณธ ๋ฌธ๋ฒ
sqlWITH ์์ํ ์ด๋ธ๋ช AS ( SELECT ์ฟผ๋ฆฌ... ) SELECT * FROM ์์ํ ์ด๋ธ๋ช ;์ค์ ์์
sql-- ๊ธฐ์กด ๋ณต์กํ ์ฟผ๋ฆฌ SELECT * FROM ( SELECT customer_id, SUM(amount) as total FROM orders WHERE order_date >= '2023-01-01' GROUP BY customer_id ) sub WHERE total > 1000; -- CTE๋ก ๊น๋ํ๊ฒ WITH customer_totals AS ( SELECT customer_id, SUM(amount) as total FROM orders WHERE order_date >= '2023-01-01' GROUP BY customer_id ) SELECT * FROM customer_totals WHERE total > 1000;
๐ CTE vs ์๋ธ์ฟผ๋ฆฌ ๋น๊ต
์๋ธ์ฟผ๋ฆฌ ๋ฐฉ์ (๋ณต์กํจ)
sql-- ์๋ธ์ฟผ๋ฆฌ: ์ฝ๊ธฐ ์ด๋ ค์ SELECT c.name, o.total_amount FROM customers c INNER JOIN ( SELECT customer_id, SUM(amount) as total_amount FROM orders WHERE status = 'completed' GROUP BY customer_id ) o ON c.id = o.customer_id WHERE o.total_amount > 500;CTE ๋ฐฉ์ (๊น๋ํจ)
sql-- CTE: ์ฝ๊ธฐ ์ฌ์ WITH completed_orders AS ( SELECT customer_id, SUM(amount) as total_amount FROM orders WHERE status = 'completed' GROUP BY customer_id ) SELECT c.name, co.total_amount FROM customers c INNER JOIN completed_orders co ON c.id = co.customer_id WHERE co.total_amount > 500;
๐ CTE์ ์ฅ์
1. ๊ฐ๋ ์ฑ ํฅ์
sql-- ๋จ๊ณ๋ณ ๋ช ํํ ๋ก์ง WITH step1 AS (๋ฐ์ดํฐ ์ถ์ถ), step2 AS (๋ฐ์ดํฐ ๊ฐ๊ณต), step3 AS (์ต์ข ์ง๊ณ) SELECT * FROM step3;2. ์ฌ์ฌ์ฉ ๊ฐ๋ฅ
sqlWITH popular_products AS ( SELECT product_id, COUNT(*) as order_count FROM orders GROUP BY product_id HAVING COUNT(*) > 100 ) -- ๊ฐ์ CTE๋ฅผ ์ฌ๋ฌ ๋ฒ ์ฌ์ฉ ๊ฐ๋ฅ SELECT p1.product_id, p1.order_count FROM popular_products p1 UNION ALL SELECT p2.product_id, p2.order_count FROM popular_products p2 WHERE p2.order_count > 200;3. ๋ณต์กํ ๋ก์ง ๋จ์ํ
sqlWITH -- 1๋จ๊ณ: ์๋ณ ๋งค์ถ monthly_sales AS ( SELECT DATE_FORMAT(order_date, '%Y-%m') as month, SUM(amount) as monthly_total FROM orders GROUP BY DATE_FORMAT(order_date, '%Y-%m') ), -- 2๋จ๊ณ: ์ ์ ๋๋น ์ฆ๊ฐ sales_growth AS ( SELECT month, monthly_total, LAG(monthly_total) OVER (ORDER BY month) as prev_month, monthly_total - LAG(monthly_total) OVER (ORDER BY month) as growth FROM monthly_sales ) -- 3๋จ๊ณ: ์ต์ข ๊ฒฐ๊ณผ SELECT month, monthly_total, growth, ROUND(growth / prev_month * 100, 2) as growth_rate FROM sales_growth WHERE prev_month IS NOT NULL;
๐ข CTE ์ ํ๋ณ ์ค๋ช
1. ์ผ๋ฐ CTE (Single CTE)
sqlWITH high_value_customers AS ( SELECT customer_id, SUM(amount) as total_spent FROM orders GROUP BY customer_id HAVING SUM(amount) > 1000 ) SELECT c.name, hvc.total_spent FROM customers c INNER JOIN high_value_customers hvc ON c.id = hvc.customer_id;2. ๋ค์ค CTE (Multiple CTEs)
sqlWITH sales_2023 AS ( SELECT * FROM orders WHERE YEAR(order_date) = 2023 ), top_customers AS ( SELECT customer_id, SUM(amount) as total FROM sales_2023 GROUP BY customer_id ORDER BY total DESC LIMIT 10 ) SELECT * FROM top_customers;3. ์ฌ๊ท CTE (Recursive CTE)
sqlWITH RECURSIVE countdown AS ( -- ์์๊ฐ SELECT 10 as num UNION ALL -- ์ฌ๊ท ๋ถ๋ถ SELECT num - 1 FROM countdown WHERE num > 1 ) SELECT * FROM countdown; -- ๊ฒฐ๊ณผ: 10, 9, 8, 7, 6, 5, 4, 3, 2, 1
๐ผ ์ค๋ฌด ํ์ฉ ์ฌ๋ก
1. ๊ณ ๊ฐ ์ธ๊ทธ๋ฉํ ์ด์
sqlWITH customer_metrics AS ( SELECT customer_id, COUNT(*) as order_count, SUM(amount) as total_spent, AVG(amount) as avg_order_value, MAX(order_date) as last_order_date FROM orders GROUP BY customer_id ), customer_segments AS ( SELECT *, CASE WHEN total_spent > 5000 AND order_count > 10 THEN 'VIP' WHEN total_spent > 1000 THEN 'Premium' WHEN order_count > 5 THEN 'Regular' ELSE 'New' END as segment FROM customer_metrics ) SELECT segment, COUNT(*) as customer_count, AVG(total_spent) as avg_spent FROM customer_segments GROUP BY segment;2. ๋งค์ถ ๋ถ์ ๋์๋ณด๋
sqlWITH daily_sales AS ( SELECT DATE(order_date) as sale_date, SUM(amount) as daily_total FROM orders WHERE order_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY) GROUP BY DATE(order_date) ), moving_average AS ( SELECT sale_date, daily_total, AVG(daily_total) OVER ( ORDER BY sale_date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW ) as ma_7day FROM daily_sales ) SELECT sale_date, daily_total, ma_7day, daily_total - ma_7day as variance FROM moving_average ORDER BY sale_date DESC;
๐ฏ ์ฝ๋ฉํ ์คํธ์์์ CTE
์์ฃผ ์ถ์ ๋๋ ํจํด
1. ๊ณ์ธต ๊ตฌ์กฐ ๋ถ์
sql-- ์นดํ ๊ณ ๋ฆฌ๋ณ ์ํ ๋ถ์ WITH category_hierarchy AS ( -- Recursive CTE๋ก ์นดํ ๊ณ ๋ฆฌ ํธ๋ฆฌ ์์ฑ ), sales_by_category AS ( -- ์นดํ ๊ณ ๋ฆฌ๋ณ ๋งค์ถ ์ง๊ณ ) SELECT * FROM sales_by_category;2. ์๊ณ์ด ๋ฐ์ดํฐ ๋ถ์
sql-- ์๋ณ ์ฑ์ฅ๋ฅ ๋ถ์ WITH monthly_metrics AS ( -- ์๋ณ ์งํ ๊ณ์ฐ ), growth_analysis AS ( -- ์ ์ ๋๋น ์ฆ๊ฐ๋ฅ ๊ณ์ฐ ) SELECT * FROM growth_analysis;3. ๋ณต์กํ ํํฐ๋ง
sql-- ์กฐ๊ฑด๋ถ ๊ณ ๊ฐ ๋ถ์ WITH qualified_customers AS ( -- 1์ฐจ ํํฐ๋ง ), final_analysis AS ( -- 2์ฐจ ๊ฐ๊ณต ) SELECT * FROM final_analysis;
โก CTE ์ฑ๋ฅ ํ
โ ์ข์ ์ฌ์ฉ
sql-- ์ธ๋ฑ์ค ํ์ฉ ๊ฐ๋ฅํ ์กฐ๊ฑด WITH filtered_data AS ( SELECT * FROM large_table WHERE indexed_column = 'value' -- ์ธ๋ฑ์ค ํ์ฉ AND date_column >= '2023-01-01' )โ ํผํด์ผ ํ ์ฌ์ฉ
sql-- ์ ์ฒด ํ ์ด๋ธ ์ค์บ ์ ๋ฐ WITH all_data AS ( SELECT * FROM large_table -- ๋๋ฌด ํฐ ์ค๊ฐ ๊ฒฐ๊ณผ์ )๐ง ์ต์ ํ ๋ฐฉ๋ฒ
sql-- 1. ํ์ํ ์ปฌ๋ผ๋ง ์ ํ WITH optimized AS ( SELECT id, amount, date_column -- ํ์ํ ์ปฌ๋ผ๋ง FROM orders WHERE date_column >= '2023-01-01' -- ์กฐ๊ธฐ ํํฐ๋ง ) -- 2. ๋จ๊ณ๋ณ ํํฐ๋ง WITH step1 AS ( SELECT * FROM table1 WHERE condition1 -- 1์ฐจ ํํฐ ), step2 AS ( SELECT * FROM step1 WHERE condition2 -- 2์ฐจ ํํฐ )
๐ CTE ๋ง์คํฐ ์ฒดํฌ๋ฆฌ์คํธ
์ด๊ธ → ์ค๊ธ
- โ ๊ธฐ๋ณธ CTE ๋ฌธ๋ฒ ์ดํด
- โ ์๋ธ์ฟผ๋ฆฌ๋ฅผ CTE๋ก ๋ณํ ๊ฐ๋ฅ
- โ ๋ค์ค CTE ์ฌ์ฉ ๊ฐ๋ฅ
์ค๊ธ → ๊ณ ๊ธ
- โ Recursive CTE ํ์ฉ
- โ ๋ณต์กํ ๋น์ฆ๋์ค ๋ก์ง์ CTE๋ก ๊ตฌ์กฐํ
- โ ์ฑ๋ฅ์ ๊ณ ๋ คํ CTE ์ค๊ณ
์ฟ ํก BA ๋ ๋ฒจ
- โ ์ค๋ฌด ์ํฉ์ CTE๋ก ๋ชจ๋ธ๋ง
- โ ๊ฐ๋ ์ฑ๊ณผ ์ฑ๋ฅ์ ๊ท ํ์ ์ฐพ๊ธฐ
- โ ํ์๋ค์ด ์ดํดํ๊ธฐ ์ฌ์ด ์ฝ๋ ์์ฑ
ํต์ฌ ์์ฝ: CTE๋ ๋ณต์กํ SQL์ ๋จ๊ณ๋ณ๋ก ๋๋ ์ ์ฝ๊ธฐ ์ฝ๊ฒ ๋ง๋๋ ๋๊ตฌ์ ๋๋ค. ๋ณต์กํ ๋ฐ์ดํฐ ๋ถ์์์๋ ํ์ ์คํฌ์ด์์! ๐
๋ฐ์ํ'Programing Language > SQL' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
ํ๋ก๊ทธ๋๋จธ์ค_๋์ฅ๊ท ์ ํฌ๊ธฐ์ ๋ฐ๋ผ ๋ถ๋ฅํ๊ธฐ 2 (0) 2025.06.14 DAYOFWEEK ํจ์ (0) 2025.06.14 ํ๋ก๊ทธ๋๋จธ์ค_๋ฉธ์ข ์๊ธฐ์ ๋์ฅ๊ท ์ฐพ๊ธฐ (0) 2025.06.13 MySQL DATETIME ์ฑ๋ฅ ์ต์ ํ ์๋ฒฝ ๊ฐ์ด๋ (0) 2025.06.13 ํ๋ก๊ทธ๋๋จธ์ค_๋์ฌ ๊ธฐ๋ก์ด ์กด์ฌํ๋ ์๋์ฐจ ๋ฆฌ์คํธ ๊ตฌํ๊ธฐ (1) 2025.06.13