04_subqueries.sql

Download
sql 367 lines 9.4 KB
  1-- =============================================================================
  2-- PostgreSQL ์„œ๋ธŒ์ฟผ๋ฆฌ์™€ CTE ์˜ˆ์ œ
  3-- Subqueries and Common Table Expressions (CTE)
  4-- =============================================================================
  5
  6-- ๋จผ์ € ์ด์ „ ์˜ˆ์ œ ํŒŒ์ผ๋“ค์„ ์‹คํ–‰ํ•˜์—ฌ ํ…Œ์ด๋ธ”๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜์„ธ์š”.
  7
  8-- =============================================================================
  9-- 1. ์Šค์นผ๋ผ ์„œ๋ธŒ์ฟผ๋ฆฌ (๋‹จ์ผ ๊ฐ’ ๋ฐ˜ํ™˜)
 10-- =============================================================================
 11
 12-- SELECT ์ ˆ์—์„œ ์‚ฌ์šฉ
 13SELECT
 14    first_name,
 15    last_name,
 16    salary,
 17    (SELECT AVG(salary) FROM employees) AS company_avg,
 18    salary - (SELECT AVG(salary) FROM employees) AS diff_from_avg
 19FROM employees;
 20
 21-- WHERE ์ ˆ์—์„œ ์‚ฌ์šฉ
 22SELECT first_name, last_name, salary
 23FROM employees
 24WHERE salary > (SELECT AVG(salary) FROM employees);
 25
 26-- ๋ถ€์„œ๋ณ„ ํ‰๊ท ๋ณด๋‹ค ๋†’์€ ๊ธ‰์—ฌ๋ฅผ ๋ฐ›๋Š” ์ง์›
 27SELECT e.first_name, e.last_name, e.salary, d.dept_name
 28FROM employees e
 29JOIN departments d ON e.dept_id = d.dept_id
 30WHERE e.salary > (
 31    SELECT AVG(salary)
 32    FROM employees
 33    WHERE dept_id = e.dept_id
 34);
 35
 36-- =============================================================================
 37-- 2. ์ธ๋ผ์ธ ๋ทฐ (FROM ์ ˆ ์„œ๋ธŒ์ฟผ๋ฆฌ)
 38-- =============================================================================
 39
 40-- ๋ถ€์„œ๋ณ„ ํ†ต๊ณ„๋ฅผ ์„œ๋ธŒ์ฟผ๋ฆฌ๋กœ ๊ตฌํ•œ ํ›„ ์กฐ์ธ
 41SELECT
 42    d.dept_name,
 43    ds.employee_count,
 44    ds.avg_salary,
 45    ds.total_salary
 46FROM departments d
 47JOIN (
 48    SELECT
 49        dept_id,
 50        COUNT(*) AS employee_count,
 51        ROUND(AVG(salary), 2) AS avg_salary,
 52        SUM(salary) AS total_salary
 53    FROM employees
 54    WHERE dept_id IS NOT NULL
 55    GROUP BY dept_id
 56) ds ON d.dept_id = ds.dept_id;
 57
 58-- ๊ธ‰์—ฌ ์ˆœ์œ„์™€ ํ•จ๊ป˜ ์กฐํšŒ
 59SELECT *
 60FROM (
 61    SELECT
 62        first_name,
 63        last_name,
 64        salary,
 65        RANK() OVER (ORDER BY salary DESC) AS salary_rank
 66    FROM employees
 67) ranked
 68WHERE salary_rank <= 5;
 69
 70-- =============================================================================
 71-- 3. EXISTS / NOT EXISTS
 72-- =============================================================================
 73
 74-- ํ”„๋กœ์ ํŠธ์— ์ฐธ์—ฌ ์ค‘์ธ ์ง์›
 75SELECT e.first_name, e.last_name
 76FROM employees e
 77WHERE EXISTS (
 78    SELECT 1
 79    FROM employee_projects ep
 80    WHERE ep.emp_id = e.emp_id
 81);
 82
 83-- ํ”„๋กœ์ ํŠธ์— ์ฐธ์—ฌํ•˜์ง€ ์•Š๋Š” ์ง์›
 84SELECT e.first_name, e.last_name
 85FROM employees e
 86WHERE NOT EXISTS (
 87    SELECT 1
 88    FROM employee_projects ep
 89    WHERE ep.emp_id = e.emp_id
 90);
 91
 92-- ์ง์›์ด ์žˆ๋Š” ๋ถ€์„œ
 93SELECT d.dept_name
 94FROM departments d
 95WHERE EXISTS (
 96    SELECT 1
 97    FROM employees e
 98    WHERE e.dept_id = d.dept_id
 99);
100
101-- =============================================================================
102-- 4. IN / NOT IN
103-- =============================================================================
104
105-- Engineering ๋ถ€์„œ ์ง์›
106SELECT first_name, last_name
107FROM employees
108WHERE dept_id IN (
109    SELECT dept_id
110    FROM departments
111    WHERE dept_name = 'Engineering'
112);
113
114-- ํ”„๋กœ์ ํŠธ์— ์ฐธ์—ฌํ•˜์ง€ ์•Š๋Š” ์ง์› (NOT IN ์ฃผ์˜: NULL ์ฒ˜๋ฆฌ)
115SELECT first_name, last_name
116FROM employees
117WHERE emp_id NOT IN (
118    SELECT emp_id FROM employee_projects
119);
120
121-- =============================================================================
122-- 5. ANY / ALL
123-- =============================================================================
124
125-- Engineering ๋ถ€์„œ์˜ ์–ด๋–ค ์ง์›๋ณด๋‹ค ๊ธ‰์—ฌ๊ฐ€ ๋†’์€ ์ง์›
126SELECT first_name, last_name, salary
127FROM employees
128WHERE salary > ANY (
129    SELECT salary
130    FROM employees e
131    JOIN departments d ON e.dept_id = d.dept_id
132    WHERE d.dept_name = 'Engineering'
133);
134
135-- Engineering ๋ถ€์„œ์˜ ๋ชจ๋“  ์ง์›๋ณด๋‹ค ๊ธ‰์—ฌ๊ฐ€ ๋†’์€ ์ง์›
136SELECT first_name, last_name, salary
137FROM employees
138WHERE salary > ALL (
139    SELECT salary
140    FROM employees e
141    JOIN departments d ON e.dept_id = d.dept_id
142    WHERE d.dept_name = 'Engineering'
143);
144
145-- =============================================================================
146-- 6. ์ƒ๊ด€ ์„œ๋ธŒ์ฟผ๋ฆฌ (Correlated Subquery)
147-- =============================================================================
148
149-- ๊ฐ ์ง์›์˜ ๋ถ€์„œ ํ‰๊ท ๊ณผ ๋น„๊ต
150SELECT
151    e.first_name,
152    e.last_name,
153    e.salary,
154    (
155        SELECT ROUND(AVG(e2.salary), 2)
156        FROM employees e2
157        WHERE e2.dept_id = e.dept_id
158    ) AS dept_avg_salary
159FROM employees e
160WHERE e.dept_id IS NOT NULL;
161
162-- ๋ถ€์„œ ๋‚ด์—์„œ ๊ฐ€์žฅ ๋†’์€ ๊ธ‰์—ฌ๋ฅผ ๋ฐ›๋Š” ์ง์›
163SELECT e.first_name, e.last_name, e.salary, d.dept_name
164FROM employees e
165JOIN departments d ON e.dept_id = d.dept_id
166WHERE e.salary = (
167    SELECT MAX(e2.salary)
168    FROM employees e2
169    WHERE e2.dept_id = e.dept_id
170);
171
172-- =============================================================================
173-- 7. CTE (Common Table Expression) - WITH ์ ˆ
174-- =============================================================================
175
176-- ๊ธฐ๋ณธ CTE
177WITH dept_stats AS (
178    SELECT
179        dept_id,
180        COUNT(*) AS employee_count,
181        ROUND(AVG(salary), 2) AS avg_salary,
182        SUM(salary) AS total_salary
183    FROM employees
184    WHERE dept_id IS NOT NULL
185    GROUP BY dept_id
186)
187SELECT
188    d.dept_name,
189    ds.employee_count,
190    ds.avg_salary,
191    ds.total_salary
192FROM departments d
193JOIN dept_stats ds ON d.dept_id = ds.dept_id
194ORDER BY ds.total_salary DESC;
195
196-- ์—ฌ๋Ÿฌ CTE ์‚ฌ์šฉ
197WITH
198high_earners AS (
199    SELECT emp_id, first_name, last_name, salary
200    FROM employees
201    WHERE salary > 50000
202),
203dept_names AS (
204    SELECT e.emp_id, d.dept_name
205    FROM employees e
206    JOIN departments d ON e.dept_id = d.dept_id
207)
208SELECT
209    h.first_name,
210    h.last_name,
211    h.salary,
212    dn.dept_name
213FROM high_earners h
214LEFT JOIN dept_names dn ON h.emp_id = dn.emp_id;
215
216-- CTE๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ์ฐธ์กฐ
217WITH emp_summary AS (
218    SELECT
219        dept_id,
220        COUNT(*) AS emp_count,
221        AVG(salary) AS avg_salary
222    FROM employees
223    GROUP BY dept_id
224)
225SELECT
226    'Total Departments' AS metric,
227    COUNT(*) AS value
228FROM emp_summary
229UNION ALL
230SELECT
231    'Avg Employees per Dept',
232    ROUND(AVG(emp_count), 2)
233FROM emp_summary
234UNION ALL
235SELECT
236    'Overall Avg Salary',
237    ROUND(AVG(avg_salary), 2)
238FROM emp_summary;
239
240-- =============================================================================
241-- 8. ์žฌ๊ท€ CTE (Recursive CTE)
242-- =============================================================================
243
244-- ์ˆซ์ž ์‹œํ€€์Šค ์ƒ์„ฑ
245WITH RECURSIVE numbers AS (
246    -- Base case
247    SELECT 1 AS n
248    UNION ALL
249    -- Recursive case
250    SELECT n + 1
251    FROM numbers
252    WHERE n < 10
253)
254SELECT n FROM numbers;
255
256-- ์กฐ์ง๋„ (์ง์›-๊ด€๋ฆฌ์ž ๊ณ„์ธต)
257WITH RECURSIVE org_chart AS (
258    -- Base case: ์ตœ์ƒ์œ„ ๊ด€๋ฆฌ์ž (manager_id๊ฐ€ NULL)
259    SELECT
260        emp_id,
261        first_name || ' ' || last_name AS name,
262        manager_id,
263        1 AS level,
264        ARRAY[emp_id] AS path
265    FROM employees
266    WHERE manager_id IS NULL
267
268    UNION ALL
269
270    -- Recursive case: ๋ถ€ํ•˜ ์ง์›
271    SELECT
272        e.emp_id,
273        e.first_name || ' ' || e.last_name,
274        e.manager_id,
275        oc.level + 1,
276        oc.path || e.emp_id
277    FROM employees e
278    JOIN org_chart oc ON e.manager_id = oc.emp_id
279)
280SELECT
281    REPEAT('  ', level - 1) || name AS employee_hierarchy,
282    level
283FROM org_chart
284ORDER BY path;
285
286-- ๋‚ ์งœ ์‹œ๋ฆฌ์ฆˆ ์ƒ์„ฑ
287WITH RECURSIVE date_series AS (
288    SELECT DATE '2024-01-01' AS date
289    UNION ALL
290    SELECT date + INTERVAL '1 day'
291    FROM date_series
292    WHERE date < DATE '2024-01-10'
293)
294SELECT date FROM date_series;
295
296-- =============================================================================
297-- 9. LATERAL JOIN (์ƒ๊ด€ ์„œ๋ธŒ์ฟผ๋ฆฌ์˜ ๋Œ€์•ˆ)
298-- =============================================================================
299
300-- ๊ฐ ๋ถ€์„œ์˜ ์ƒ์œ„ 2๋ช…
301SELECT d.dept_name, top_employees.*
302FROM departments d
303CROSS JOIN LATERAL (
304    SELECT first_name, last_name, salary
305    FROM employees e
306    WHERE e.dept_id = d.dept_id
307    ORDER BY salary DESC
308    LIMIT 2
309) AS top_employees;
310
311-- =============================================================================
312-- 10. ์„œ๋ธŒ์ฟผ๋ฆฌ vs CTE vs LATERAL ๋น„๊ต
313-- =============================================================================
314
315-- ๋ฐฉ๋ฒ• 1: ์„œ๋ธŒ์ฟผ๋ฆฌ (์ธ๋ผ์ธ ๋ทฐ)
316SELECT *
317FROM (
318    SELECT dept_id, AVG(salary) AS avg_sal
319    FROM employees
320    GROUP BY dept_id
321) sub
322WHERE avg_sal > 50000;
323
324-- ๋ฐฉ๋ฒ• 2: CTE (๋” ์ฝ๊ธฐ ์‰ฌ์›€)
325WITH dept_avg AS (
326    SELECT dept_id, AVG(salary) AS avg_sal
327    FROM employees
328    GROUP BY dept_id
329)
330SELECT * FROM dept_avg WHERE avg_sal > 50000;
331
332-- ๋ฐฉ๋ฒ• 3: LATERAL (ํ–‰๋ณ„๋กœ ์„œ๋ธŒ์ฟผ๋ฆฌ ํ•„์š”ํ•  ๋•Œ)
333SELECT d.dept_name, stats.avg_salary
334FROM departments d
335CROSS JOIN LATERAL (
336    SELECT ROUND(AVG(salary), 2) AS avg_salary
337    FROM employees e
338    WHERE e.dept_id = d.dept_id
339) stats
340WHERE stats.avg_salary > 50000;
341
342-- =============================================================================
343-- ์„œ๋ธŒ์ฟผ๋ฆฌ์™€ CTE ์š”์•ฝ
344-- =============================================================================
345/*
346์„œ๋ธŒ์ฟผ๋ฆฌ ์œ„์น˜:
347- SELECT: ์Šค์นผ๋ผ ์„œ๋ธŒ์ฟผ๋ฆฌ (๋‹จ์ผ ๊ฐ’)
348- FROM: ์ธ๋ผ์ธ ๋ทฐ (ํ…Œ์ด๋ธ”์ฒ˜๋Ÿผ ์‚ฌ์šฉ)
349- WHERE: ์กฐ๊ฑด์—์„œ ์‚ฌ์šฉ
350
351์„œ๋ธŒ์ฟผ๋ฆฌ ์—ฐ์‚ฐ์ž:
352- =, <, >: ์Šค์นผ๋ผ ๋น„๊ต
353- IN, NOT IN: ๋ชฉ๋ก ํฌํ•จ ์—ฌ๋ถ€
354- EXISTS, NOT EXISTS: ์กด์žฌ ์—ฌ๋ถ€
355- ANY, ALL: ์กฐ๊ฑด ๋น„๊ต
356
357CTE ์žฅ์ :
358- ๊ฐ€๋…์„ฑ ํ–ฅ์ƒ
359- ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅ
360- ์žฌ๊ท€ ์ฟผ๋ฆฌ ์ง€์›
361- ์‹คํ–‰ ๊ณ„ํš ์ตœ์ ํ™” ํžŒํŠธ (MATERIALIZED)
362
363LATERAL:
364- ํ–‰๋ณ„๋กœ ์ƒ๊ด€ ์„œ๋ธŒ์ฟผ๋ฆฌ ์‹คํ–‰
365- TOP-N ๋ฌธ์ œ์— ์œ ์šฉ
366*/