03_aggregation.sql

Download
sql 296 lines 8.7 KB
  1-- =============================================================================
  2-- PostgreSQL ์ง‘๊ณ„ ํ•จ์ˆ˜ ์˜ˆ์ œ
  3-- Aggregation Functions and GROUP BY
  4-- =============================================================================
  5
  6-- ๋จผ์ € 01_basic_crud.sql๊ณผ 02_joins.sql์„ ์‹คํ–‰ํ•˜์—ฌ ํ…Œ์ด๋ธ”๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜์„ธ์š”.
  7
  8-- =============================================================================
  9-- 1. ๊ธฐ๋ณธ ์ง‘๊ณ„ ํ•จ์ˆ˜
 10-- =============================================================================
 11
 12-- COUNT - ํ–‰ ๊ฐœ์ˆ˜
 13SELECT COUNT(*) AS total_employees FROM employees;
 14
 15SELECT COUNT(email) AS employees_with_email FROM employees;  -- NULL ์ œ์™ธ
 16
 17SELECT COUNT(DISTINCT dept_id) AS unique_departments FROM employees;
 18
 19-- SUM - ํ•ฉ๊ณ„
 20SELECT SUM(salary) AS total_salary FROM employees;
 21
 22-- AVG - ํ‰๊ท 
 23SELECT AVG(salary) AS average_salary FROM employees;
 24
 25SELECT ROUND(AVG(salary), 2) AS avg_salary_rounded FROM employees;
 26
 27-- MIN, MAX - ์ตœ์†Ÿ๊ฐ’, ์ตœ๋Œ“๊ฐ’
 28SELECT
 29    MIN(salary) AS min_salary,
 30    MAX(salary) AS max_salary
 31FROM employees;
 32
 33SELECT
 34    MIN(hire_date) AS first_hire,
 35    MAX(hire_date) AS last_hire
 36FROM employees;
 37
 38-- ๋ชจ๋“  ์ง‘๊ณ„ ํ•จ์ˆ˜ ํ•จ๊ป˜ ์‚ฌ์šฉ
 39SELECT
 40    COUNT(*) AS employee_count,
 41    SUM(salary) AS total_salary,
 42    ROUND(AVG(salary), 2) AS avg_salary,
 43    MIN(salary) AS min_salary,
 44    MAX(salary) AS max_salary,
 45    MAX(salary) - MIN(salary) AS salary_range
 46FROM employees;
 47
 48-- =============================================================================
 49-- 2. GROUP BY
 50-- =============================================================================
 51
 52-- ๋ถ€์„œ๋ณ„ ์ง‘๊ณ„
 53SELECT
 54    dept_id,
 55    COUNT(*) AS employee_count,
 56    ROUND(AVG(salary), 2) AS avg_salary
 57FROM employees
 58WHERE dept_id IS NOT NULL
 59GROUP BY dept_id
 60ORDER BY employee_count DESC;
 61
 62-- JOIN๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉ
 63SELECT
 64    d.dept_name,
 65    COUNT(e.emp_id) AS employee_count,
 66    SUM(e.salary) AS total_salary,
 67    ROUND(AVG(e.salary), 2) AS avg_salary
 68FROM departments d
 69LEFT JOIN employees e ON d.dept_id = e.dept_id
 70GROUP BY d.dept_id, d.dept_name
 71ORDER BY total_salary DESC NULLS LAST;
 72
 73-- ์—ฌ๋Ÿฌ ์ปฌ๋Ÿผ์œผ๋กœ ๊ทธ๋ฃนํ™”
 74SELECT
 75    dept_id,
 76    is_active,
 77    COUNT(*) AS employee_count
 78FROM employees
 79GROUP BY dept_id, is_active
 80ORDER BY dept_id, is_active;
 81
 82-- ํ‘œํ˜„์‹์œผ๋กœ ๊ทธ๋ฃนํ™”
 83SELECT
 84    EXTRACT(YEAR FROM hire_date) AS hire_year,
 85    COUNT(*) AS hire_count
 86FROM employees
 87GROUP BY EXTRACT(YEAR FROM hire_date)
 88ORDER BY hire_year;
 89
 90-- =============================================================================
 91-- 3. HAVING - ๊ทธ๋ฃน ํ•„ํ„ฐ๋ง
 92-- =============================================================================
 93
 94-- ์ง์›์ด 2๋ช… ์ด์ƒ์ธ ๋ถ€์„œ
 95SELECT
 96    d.dept_name,
 97    COUNT(e.emp_id) AS employee_count
 98FROM departments d
 99JOIN employees e ON d.dept_id = e.dept_id
100GROUP BY d.dept_id, d.dept_name
101HAVING COUNT(e.emp_id) >= 2
102ORDER BY employee_count DESC;
103
104-- ํ‰๊ท  ๊ธ‰์—ฌ๊ฐ€ 50000 ์ด์ƒ์ธ ๋ถ€์„œ
105SELECT
106    d.dept_name,
107    ROUND(AVG(e.salary), 2) AS avg_salary
108FROM departments d
109JOIN employees e ON d.dept_id = e.dept_id
110GROUP BY d.dept_id, d.dept_name
111HAVING AVG(e.salary) >= 50000
112ORDER BY avg_salary DESC;
113
114-- WHERE์™€ HAVING ํ•จ๊ป˜ ์‚ฌ์šฉ
115SELECT
116    d.dept_name,
117    COUNT(e.emp_id) AS employee_count,
118    ROUND(AVG(e.salary), 2) AS avg_salary
119FROM departments d
120JOIN employees e ON d.dept_id = e.dept_id
121WHERE e.is_active = TRUE  -- ํ–‰ ํ•„ํ„ฐ๋ง (๊ทธ๋ฃน ์ „)
122GROUP BY d.dept_id, d.dept_name
123HAVING COUNT(e.emp_id) >= 1  -- ๊ทธ๋ฃน ํ•„ํ„ฐ๋ง (๊ทธ๋ฃน ํ›„)
124ORDER BY avg_salary DESC;
125
126-- =============================================================================
127-- 4. ๊ณ ๊ธ‰ ์ง‘๊ณ„ ํ•จ์ˆ˜
128-- =============================================================================
129
130-- STRING_AGG - ๋ฌธ์ž์—ด ์—ฐ๊ฒฐ
131SELECT
132    d.dept_name,
133    STRING_AGG(e.first_name || ' ' || e.last_name, ', ' ORDER BY e.first_name) AS employee_names
134FROM departments d
135JOIN employees e ON d.dept_id = e.dept_id
136GROUP BY d.dept_id, d.dept_name;
137
138-- ARRAY_AGG - ๋ฐฐ์—ด๋กœ ์ง‘๊ณ„
139SELECT
140    d.dept_name,
141    ARRAY_AGG(e.first_name ORDER BY e.first_name) AS employee_names_array
142FROM departments d
143JOIN employees e ON d.dept_id = e.dept_id
144GROUP BY d.dept_id, d.dept_name;
145
146-- JSON_AGG - JSON ๋ฐฐ์—ด๋กœ ์ง‘๊ณ„
147SELECT
148    d.dept_name,
149    JSON_AGG(
150        JSON_BUILD_OBJECT(
151            'name', e.first_name || ' ' || e.last_name,
152            'salary', e.salary
153        )
154    ) AS employees_json
155FROM departments d
156JOIN employees e ON d.dept_id = e.dept_id
157GROUP BY d.dept_id, d.dept_name;
158
159-- =============================================================================
160-- 5. ROLLUP, CUBE, GROUPING SETS
161-- =============================================================================
162
163-- ROLLUP - ๊ณ„์ธต์  ์†Œ๊ณ„
164SELECT
165    d.dept_name,
166    EXTRACT(YEAR FROM e.hire_date) AS hire_year,
167    COUNT(*) AS employee_count,
168    SUM(e.salary) AS total_salary
169FROM employees e
170JOIN departments d ON e.dept_id = d.dept_id
171GROUP BY ROLLUP(d.dept_name, EXTRACT(YEAR FROM e.hire_date))
172ORDER BY d.dept_name NULLS LAST, hire_year NULLS LAST;
173
174-- CUBE - ๋ชจ๋“  ๊ฐ€๋Šฅํ•œ ์กฐํ•ฉ์˜ ์†Œ๊ณ„
175SELECT
176    d.dept_name,
177    e.is_active,
178    COUNT(*) AS employee_count
179FROM employees e
180JOIN departments d ON e.dept_id = d.dept_id
181GROUP BY CUBE(d.dept_name, e.is_active)
182ORDER BY d.dept_name NULLS LAST, e.is_active NULLS LAST;
183
184-- GROUPING SETS - ํŠน์ • ์กฐํ•ฉ๋งŒ ์†Œ๊ณ„
185SELECT
186    d.dept_name,
187    EXTRACT(YEAR FROM e.hire_date) AS hire_year,
188    COUNT(*) AS employee_count
189FROM employees e
190JOIN departments d ON e.dept_id = d.dept_id
191GROUP BY GROUPING SETS (
192    (d.dept_name),
193    (EXTRACT(YEAR FROM e.hire_date)),
194    ()
195)
196ORDER BY d.dept_name NULLS LAST, hire_year NULLS LAST;
197
198-- GROUPING() ํ•จ์ˆ˜๋กœ ์†Œ๊ณ„ ํ–‰ ๊ตฌ๋ถ„
199SELECT
200    CASE WHEN GROUPING(d.dept_name) = 1 THEN 'All Departments' ELSE d.dept_name END AS dept_name,
201    COUNT(*) AS employee_count,
202    SUM(e.salary) AS total_salary
203FROM employees e
204JOIN departments d ON e.dept_id = d.dept_id
205GROUP BY ROLLUP(d.dept_name)
206ORDER BY GROUPING(d.dept_name), d.dept_name;
207
208-- =============================================================================
209-- 6. FILTER ์ ˆ
210-- =============================================================================
211
212-- ์กฐ๊ฑด๋ณ„๋กœ ๋‹ค๋ฅธ ์ง‘๊ณ„
213SELECT
214    d.dept_name,
215    COUNT(*) AS total_count,
216    COUNT(*) FILTER (WHERE e.salary > 50000) AS high_salary_count,
217    COUNT(*) FILTER (WHERE e.salary <= 50000) AS low_salary_count,
218    ROUND(AVG(e.salary) FILTER (WHERE e.is_active = TRUE), 2) AS active_avg_salary
219FROM departments d
220JOIN employees e ON d.dept_id = e.dept_id
221GROUP BY d.dept_id, d.dept_name;
222
223-- =============================================================================
224-- 7. ํ†ต๊ณ„ ํ•จ์ˆ˜
225-- =============================================================================
226
227-- ํ‘œ์ค€ํŽธ์ฐจ์™€ ๋ถ„์‚ฐ
228SELECT
229    d.dept_name,
230    ROUND(AVG(e.salary), 2) AS avg_salary,
231    ROUND(STDDEV(e.salary), 2) AS stddev_salary,
232    ROUND(VARIANCE(e.salary), 2) AS variance_salary
233FROM departments d
234JOIN employees e ON d.dept_id = e.dept_id
235GROUP BY d.dept_id, d.dept_name
236HAVING COUNT(*) > 1;  -- ํ‘œ์ค€ํŽธ์ฐจ๋Š” 2๊ฐœ ์ด์ƒ ํ•„์š”
237
238-- ๋ฐฑ๋ถ„์œ„์ˆ˜
239SELECT
240    PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY salary) AS median_salary,
241    PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY salary) AS q1_salary,
242    PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY salary) AS q3_salary
243FROM employees;
244
245-- ์ตœ๋นˆ๊ฐ’ (MODE)
246SELECT
247    MODE() WITHIN GROUP (ORDER BY dept_id) AS most_common_dept
248FROM employees;
249
250-- =============================================================================
251-- 8. ์กฐ๊ฑด๋ถ€ ์ง‘๊ณ„ (CASE์™€ ํ•จ๊ป˜)
252-- =============================================================================
253
254SELECT
255    d.dept_name,
256    COUNT(*) AS total,
257    SUM(CASE WHEN e.salary >= 55000 THEN 1 ELSE 0 END) AS high_earners,
258    SUM(CASE WHEN e.salary < 55000 THEN 1 ELSE 0 END) AS others,
259    ROUND(
260        100.0 * SUM(CASE WHEN e.salary >= 55000 THEN 1 ELSE 0 END) / COUNT(*),
261        1
262    ) AS high_earner_pct
263FROM departments d
264JOIN employees e ON d.dept_id = e.dept_id
265GROUP BY d.dept_id, d.dept_name;
266
267-- =============================================================================
268-- ์ง‘๊ณ„ ํ•จ์ˆ˜ ์š”์•ฝ
269-- =============================================================================
270/*
271๊ธฐ๋ณธ ์ง‘๊ณ„:
272- COUNT(*), COUNT(col), COUNT(DISTINCT col)
273- SUM(col), AVG(col)
274- MIN(col), MAX(col)
275
276๋ฌธ์ž์—ด/๋ฐฐ์—ด ์ง‘๊ณ„:
277- STRING_AGG(col, delimiter)
278- ARRAY_AGG(col)
279- JSON_AGG(value)
280
281๊ทธ๋ฃนํ™”:
282- GROUP BY: ๊ธฐ๋ณธ ๊ทธ๋ฃนํ™”
283- HAVING: ๊ทธ๋ฃน ํ•„ํ„ฐ๋ง (์ง‘๊ณ„ ํ›„)
284- ROLLUP: ๊ณ„์ธต์  ์†Œ๊ณ„
285- CUBE: ๋ชจ๋“  ์กฐํ•ฉ ์†Œ๊ณ„
286- GROUPING SETS: ํŠน์ • ์กฐํ•ฉ ์†Œ๊ณ„
287
288๊ณ ๊ธ‰:
289- FILTER (WHERE ...): ์กฐ๊ฑด๋ถ€ ์ง‘๊ณ„
290- PERCENTILE_CONT(): ๋ฐฑ๋ถ„์œ„์ˆ˜
291- STDDEV(), VARIANCE(): ํ†ต๊ณ„
292
293์ˆœ์„œ:
294SELECT โ†’ FROM โ†’ WHERE โ†’ GROUP BY โ†’ HAVING โ†’ ORDER BY โ†’ LIMIT
295*/