2. SQL - group by (#1)

Jasonยท2026๋…„ 1์›” 12์ผ

SQL

๋ชฉ๋ก ๋ณด๊ธฐ
2/47

์ง‘๊ณ„ํ•จ์ˆ˜, HAVING

SQL GROUP BY & ์ง‘๊ณ„ํ•จ์ˆ˜ โ€” ๋ฐ์ดํ„ฐ ์š”์•ฝ์˜ ๊ธฐ์ˆ 

๐Ÿ’ก ๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ๋ฃน์œผ๋กœ ๋ฌถ๊ณ  ์š”์•ฝํ•˜๋Š” ํ•ต์‹ฌ ๊ธฐ์ˆ ์„ ์ •๋ฆฌํ•œ๋‹ค.


๐Ÿค” GROUP BY๊ฐ€ ๋ญ์•ผ?

๋ฐ์ดํ„ฐ๋ฅผ ํŠน์ • ๊ธฐ์ค€์œผ๋กœ ๋ฌถ์–ด์„œ ์ง‘๊ณ„ํ•˜๋Š” ๊ฒƒ.

์˜ˆ: "์œ ์ €๋ณ„ ์ด ์ฃผ๋ฌธ ๊ธˆ์•ก", "์›”๋ณ„ ๋งค์ถœ", "์ƒํ’ˆ๋ณ„ ํŒ๋งค ์ˆ˜๋Ÿ‰"

โ†’ ์ด๋Ÿฐ ์งˆ๋ฌธ์— ๋‹ตํ•˜๋ ค๋ฉด GROUP BY ํ•„์ˆ˜!


๐Ÿ“Š ์˜ˆ์ œ ํ…Œ์ด๋ธ”

[orders]
| order_id | user_id | product | amount | order_date |
|----------|---------|---------|--------|------------|
| 1 | 101 | ๋…ธํŠธ๋ถ | 1500000 | 2024-01-15 |
| 2 | 101 | ๋งˆ์šฐ์Šค | 50000 | 2024-01-20 |
| 3 | 102 | ํ‚ค๋ณด๋“œ | 100000 | 2024-01-25 |
| 4 | 102 | ๋ชจ๋‹ˆํ„ฐ | 300000 | 2024-02-10 |
| 5 | 103 | ๋…ธํŠธ๋ถ | 1500000 | 2024-02-15 |
| 6 | 101 | ํ‚ค๋ณด๋“œ | 100000 | 2024-02-20 |


๐Ÿ“ˆ ์ง‘๊ณ„ํ•จ์ˆ˜ ์ข…๋ฅ˜

ํ•จ์ˆ˜์„ค๋ช…์˜ˆ์‹œ
COUNT()๊ฐœ์ˆ˜COUNT(*), COUNT(column)
SUM()ํ•ฉ๊ณ„SUM(amount)
AVG()ํ‰๊ท AVG(amount)
MAX()์ตœ๋Œ€๊ฐ’MAX(amount)
MIN()์ตœ์†Œ๊ฐ’MIN(amount)

1๏ธโƒฃ ๊ธฐ๋ณธ ์ง‘๊ณ„ (GROUP BY ์—†์ด)

์ „์ฒด ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์ง‘๊ณ„:

SELECT 
    COUNT(*) AS ์ด_์ฃผ๋ฌธ์ˆ˜,
    SUM(amount) AS ์ด_๋งค์ถœ,
    AVG(amount) AS ํ‰๊ท _์ฃผ๋ฌธ๊ธˆ์•ก,
    MAX(amount) AS ์ตœ๋Œ€_์ฃผ๋ฌธ๊ธˆ์•ก,
    MIN(amount) AS ์ตœ์†Œ_์ฃผ๋ฌธ๊ธˆ์•ก
FROM orders;
์ด_์ฃผ๋ฌธ์ˆ˜์ด_๋งค์ถœํ‰๊ท _์ฃผ๋ฌธ๊ธˆ์•ก์ตœ๋Œ€_์ฃผ๋ฌธ๊ธˆ์•ก์ตœ์†Œ_์ฃผ๋ฌธ๊ธˆ์•ก
63550000591667150000050000

2๏ธโƒฃ GROUP BY ๊ธฐ๋ณธ

์œ ์ €๋ณ„ ์ฃผ๋ฌธ ์ง‘๊ณ„

SELECT 
    user_id,
    COUNT(*) AS ์ฃผ๋ฌธ์ˆ˜,
    SUM(amount) AS ์ด_์ฃผ๋ฌธ๊ธˆ์•ก
FROM orders
GROUP BY user_id;
user_id์ฃผ๋ฌธ์ˆ˜์ด_์ฃผ๋ฌธ๊ธˆ์•ก
10131650000
1022400000
10311500000

์ƒํ’ˆ๋ณ„ ํŒ๋งค ์ง‘๊ณ„

SELECT 
    product,
    COUNT(*) AS ํŒ๋งค์ˆ˜,
    SUM(amount) AS ์ด_๋งค์ถœ
FROM orders
GROUP BY product;
productํŒ๋งค์ˆ˜์ด_๋งค์ถœ
๋…ธํŠธ๋ถ23000000
๋งˆ์šฐ์Šค150000
ํ‚ค๋ณด๋“œ2200000
๋ชจ๋‹ˆํ„ฐ1300000

3๏ธโƒฃ ์—ฌ๋Ÿฌ ์ปฌ๋Ÿผ์œผ๋กœ GROUP BY

์œ ์ €๋ณ„ + ์ƒํ’ˆ๋ณ„

SELECT 
    user_id,
    product,
    COUNT(*) AS ๊ตฌ๋งคํšŸ์ˆ˜,
    SUM(amount) AS ์ด์•ก
FROM orders
GROUP BY user_id, product;
user_idproduct๊ตฌ๋งคํšŸ์ˆ˜์ด์•ก
101๋…ธํŠธ๋ถ11500000
101๋งˆ์šฐ์Šค150000
101ํ‚ค๋ณด๋“œ1100000
102ํ‚ค๋ณด๋“œ1100000
102๋ชจ๋‹ˆํ„ฐ1300000
103๋…ธํŠธ๋ถ11500000

4๏ธโƒฃ ๋‚ ์งœ๋ณ„ GROUP BY

์›”๋ณ„ ๋งค์ถœ

SELECT 
    DATE_FORMAT(order_date, '%Y-%m') AS ์›”,
    COUNT(*) AS ์ฃผ๋ฌธ์ˆ˜,
    SUM(amount) AS ๋งค์ถœ
FROM orders
GROUP BY DATE_FORMAT(order_date, '%Y-%m');
์›”์ฃผ๋ฌธ์ˆ˜๋งค์ถœ
2024-0131650000
2024-0231900000

๋‚ ์งœ ํ•จ์ˆ˜ ์ •๋ฆฌ

DB์—ฐ-์›” ์ถ”์ถœ
MySQLDATE_FORMAT(date, '%Y-%m')
PostgreSQLTO_CHAR(date, 'YYYY-MM')
BigQueryFORMAT_DATE('%Y-%m', date)

5๏ธโƒฃ HAVING โ€” ๊ทธ๋ฃน ํ•„ํ„ฐ๋ง

WHERE vs HAVING

์ ˆ์‹œ์ ๋Œ€์ƒ
WHEREGROUP BY ์ „๊ฐœ๋ณ„ ํ–‰
HAVINGGROUP BY ํ›„๊ทธ๋ฃน ๊ฒฐ๊ณผ

์˜ˆ์ œ: ์ฃผ๋ฌธ 2ํšŒ ์ด์ƒ์ธ ์œ ์ €๋งŒ

SELECT 
    user_id,
    COUNT(*) AS ์ฃผ๋ฌธ์ˆ˜,
    SUM(amount) AS ์ด์•ก
FROM orders
GROUP BY user_id
HAVING COUNT(*) >= 2;
user_id์ฃผ๋ฌธ์ˆ˜์ด์•ก
10131650000
1022400000

WHERE + HAVING ์กฐํ•ฉ

-- 2024๋…„ ์ฃผ๋ฌธ ์ค‘, ์ด์•ก 100๋งŒ์› ์ด์ƒ์ธ ์œ ์ €
SELECT 
    user_id,
    SUM(amount) AS ์ด์•ก
FROM orders
WHERE order_date >= '2024-01-01'  -- ํ–‰ ํ•„ํ„ฐ๋ง
GROUP BY user_id
HAVING SUM(amount) >= 1000000;    -- ๊ทธ๋ฃน ํ•„ํ„ฐ๋ง

6๏ธโƒฃ COUNT ์‹ฌํ™”

COUNT(*) vs COUNT(column)

SELECT 
    COUNT(*) AS ์ „์ฒดํ–‰,           -- NULL ํฌํ•จ
    COUNT(user_id) AS user_id์ˆ˜,  -- NULL ์ œ์™ธ
    COUNT(DISTINCT user_id) AS ์œ ์ €์ˆ˜  -- ์ค‘๋ณต ์ œ์™ธ
FROM orders;
์ „์ฒดํ–‰user_id์ˆ˜์œ ์ €์ˆ˜
663

DISTINCT์™€ ํ•จ๊ป˜

-- ์ฃผ๋ฌธํ•œ ์œ ์ € ์ˆ˜ (์ค‘๋ณต ์ œ์™ธ)
SELECT COUNT(DISTINCT user_id) AS ๊ตฌ๋งค_์œ ์ €์ˆ˜
FROM orders;

7๏ธโƒฃ ์‹คํ–‰ ์ˆœ์„œ ์ดํ•ดํ•˜๊ธฐ

SQL ์‹คํ–‰ ์ˆœ์„œ:

FROM     โ†’ ํ…Œ์ด๋ธ” ์„ ํƒ
WHERE    โ†’ ํ–‰ ํ•„ํ„ฐ๋ง
GROUP BY โ†’ ๊ทธ๋ฃนํ™”
HAVING   โ†’ ๊ทธ๋ฃน ํ•„ํ„ฐ๋ง
SELECT   โ†’ ์ปฌ๋Ÿผ ์„ ํƒ
ORDER BY โ†’ ์ •๋ ฌ
LIMIT    โ†’ ๊ฐœ์ˆ˜ ์ œํ•œ

์™œ ์ค‘์š”ํ•ด?

-- โŒ ์—๋Ÿฌ! SELECT์˜ ๋ณ„์นญ์„ WHERE์—์„œ ๋ชป ์”€
SELECT user_id, SUM(amount) AS total
FROM orders
WHERE total > 100000  -- ์•„์ง total ์—†์Œ!
GROUP BY user_id;

-- โœ… HAVING ์‚ฌ์šฉ
SELECT user_id, SUM(amount) AS total
FROM orders
GROUP BY user_id
HAVING SUM(amount) > 100000;

๐ŸŽฏ ์‹ค์ „ ๋ฌธ์ œ

๋ฌธ์ œ 1: ๊ธฐ๋ณธ GROUP BY

์ƒํ’ˆ๋ณ„ ํ‰๊ท  ์ฃผ๋ฌธ ๊ธˆ์•ก์„ ๊ตฌํ•˜์„ธ์š”. ํ‰๊ท  ๊ธˆ์•ก ๋‚ด๋ฆผ์ฐจ์ˆœ ์ •๋ ฌ.

์ •๋‹ต ๋ณด๊ธฐ
SELECT 
    product,
    AVG(amount) AS avg_amount
FROM orders
GROUP BY product
ORDER BY avg_amount DESC;

๋ฌธ์ œ 2: HAVING ํ™œ์šฉ

์ด ์ฃผ๋ฌธ ๊ธˆ์•ก์ด 50๋งŒ์› ์ด์ƒ์ธ ์œ ์ €์˜ user_id์™€ ์ด ๊ธˆ์•ก์„ ๊ตฌํ•˜์„ธ์š”.

์ •๋‹ต ๋ณด๊ธฐ
SELECT 
    user_id,
    SUM(amount) AS total_amount
FROM orders
GROUP BY user_id
HAVING SUM(amount) >= 500000;

๋ฌธ์ œ 3: ๋ณตํ•ฉ ์กฐ๊ฑด

2024๋…„ 1์›”์— 2ํšŒ ์ด์ƒ ์ฃผ๋ฌธํ•œ ์œ ์ €์˜ user_id, ์ฃผ๋ฌธ ํšŸ์ˆ˜, ์ด์•ก์„ ๊ตฌํ•˜์„ธ์š”.

์ •๋‹ต ๋ณด๊ธฐ
SELECT 
    user_id,
    COUNT(*) AS order_count,
    SUM(amount) AS total_amount
FROM orders
WHERE order_date >= '2024-01-01' 
  AND order_date < '2024-02-01'
GROUP BY user_id
HAVING COUNT(*) >= 2;

๋ฌธ์ œ 4: JOIN + GROUP BY

์œ ์ €๋ณ„ ์ด๋ฆ„๊ณผ ์ด ์ฃผ๋ฌธ ๊ธˆ์•ก์„ ๊ตฌํ•˜์„ธ์š”. (users ํ…Œ์ด๋ธ”๊ณผ JOIN)

์ •๋‹ต ๋ณด๊ธฐ
SELECT 
    u.name,
    SUM(o.amount) AS total_amount
FROM users u
JOIN orders o ON u.user_id = o.user_id
GROUP BY u.user_id, u.name;

๐Ÿ’ก ์ž์ฃผ ํ•˜๋Š” ์‹ค์ˆ˜

1. SELECT์— GROUP BY ์•ˆ ํ•œ ์ปฌ๋Ÿผ ๋„ฃ๊ธฐ

-- โŒ ์—๋Ÿฌ (์—„๊ฒฉ ๋ชจ๋“œ์—์„œ)
SELECT user_id, product, SUM(amount)
FROM orders
GROUP BY user_id;  -- product๋Š” GROUP BY์— ์—†์Œ!

-- โœ… ์ˆ˜์ •
SELECT user_id, product, SUM(amount)
FROM orders
GROUP BY user_id, product;

2. WHERE์—์„œ ์ง‘๊ณ„ํ•จ์ˆ˜ ์‚ฌ์šฉ

-- โŒ ์—๋Ÿฌ
SELECT user_id, SUM(amount)
FROM orders
WHERE SUM(amount) > 100000  -- ์ง‘๊ณ„ํ•จ์ˆ˜๋Š” WHERE์—์„œ ๋ชป ์”€!
GROUP BY user_id;

-- โœ… HAVING ์‚ฌ์šฉ
SELECT user_id, SUM(amount)
FROM orders
GROUP BY user_id
HAVING SUM(amount) > 100000;

3. NULL ์ฒ˜๋ฆฌ ์•ˆ ํ•จ

-- amount๊ฐ€ NULL์ธ ํ–‰์ด ์žˆ๋‹ค๋ฉด?
SELECT SUM(amount) FROM orders;  -- NULL ํ–‰์€ ๋ฌด์‹œ๋จ

-- NULL์„ 0์œผ๋กœ ์ฒ˜๋ฆฌ
SELECT SUM(COALESCE(amount, 0)) FROM orders;

๐Ÿ“ ํ•ต์‹ฌ ์ •๋ฆฌ

[์ง‘๊ณ„ํ•จ์ˆ˜]
COUNT, SUM, AVG, MAX, MIN

[GROUP BY]
ํŠน์ • ์ปฌ๋Ÿผ ๊ธฐ์ค€์œผ๋กœ ๋ฐ์ดํ„ฐ ๋ฌถ๊ธฐ

[HAVING]
๊ทธ๋ฃนํ™” ํ›„ ํ•„ํ„ฐ๋ง (WHERE๋Š” ๊ทธ๋ฃนํ™” ์ „)

[์‹คํ–‰์ˆœ์„œ]
FROM โ†’ WHERE โ†’ GROUP BY โ†’ HAVING โ†’ SELECT โ†’ ORDER BY

๐Ÿ”— ๋‹ค์Œ ํฌ์ŠคํŠธ

[SQL ์‹œ๋ฆฌ์ฆˆ #3] ์„œ๋ธŒ์ฟผ๋ฆฌ โ€” ์ฟผ๋ฆฌ ์•ˆ์˜ ์ฟผ๋ฆฌ


๐Ÿ“ GROUP BY๋Š” ๋ฐ์ดํ„ฐ ๋ถ„์„์˜ ๊ธฐ๋ณธ์ด๋‹ค.
"~๋ณ„๋กœ ์ง‘๊ณ„ํ•ด์ค˜"๋ผ๋Š” ์š”์ฒญ์ด ์˜ค๋ฉด GROUP BY๋ฅผ ๋– ์˜ฌ๋ฆฌ์ž!

profile
Data Analyst | Thoughts Become Things. ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•  ์ˆ˜ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ํ•  ์ˆ˜ ์—†๋‹ค. | www.linkedin.com/in/๋ช…์ˆ˜-์ œ-7ab843200

0๊ฐœ์˜ ๋Œ“๊ธ€