์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- TIL
- ์บ๊ธ
- ๋ฐ์ดํฐ๋ถ์
- ๋ฐ์ดํฐ ๋ถ์
- ์ฝ๋์นดํ
- ํ๋ก๊ทธ๋๋จธ์ค
- ํ์ด์ฌ
- ์๋์ฐ ํจ์
- sqld
- sql
- ๋ง์ผํ
- ์ฝ๋ฉ
- ๋ ํ
- ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ
- ๋จธ์ ๋ฌ๋
- Today
- Total
SQL & Python Study
[D+5] ์์ ๋ณด๋ค ์ฌ์ด SQL(5) - ๊ธฐ์ค ๋ฐ์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ, ํผ๋ฒ ํ ์ด๋ธ ์ ์, ์๋์ฐ ํจ์(rank, sum) ๋ณธ๋ฌธ
[D+5] ์์ ๋ณด๋ค ์ฌ์ด SQL(5) - ๊ธฐ์ค ๋ฐ์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ, ํผ๋ฒ ํ ์ด๋ธ ์ ์, ์๋์ฐ ํจ์(rank, sum)
๊น์ฎ์ 2024. 4. 19. 18:10
โ๏ธ STUDY INDEX
1. ๊ธฐ์ค ๋ฐ์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ (NULL ๊ฐ, ๋น์์์ ์ธ ๋ฐ์ดํฐ)
2. SQL ํผ๋ฒํ ์ด๋ธ(Pivot Table) ์ ์ํ๊ธฐ
3. ์๋์ฐ ํจ์ Window Function
- โ N๋ฒ์งธ๊น์ง ๋์์ ์กฐํํ๊ณ ์ถ์ ๋ rank() over()
- โก ์ ์ฒด์์ ์ฐจ์งํ๋ ๋น์จ, ๋์ ํฉ์ ๊ตฌํ๊ณ ์ถ์ ๋ sum() over()
1. ๊ธฐ์ค ๋ฐ์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ (NULL ๊ฐ, ๋น์์์ ์ธ ๋ฐ์ดํฐ)
๋ฐ์ดํฐ๋ฅผ ์กฐํ ๋๋ ์ง๊ณํ๋ค ๋ณด๋ฉด
null(๋ฐ์ดํฐ ์์) ๊ฐ์ด๋ ๋น์์์ ์ธ ๋ฐ์ดํฐ(ex. ๊ณ ๊ฐ ๋์ด 2000์ด)๊ฐ ์กด์ฌํ๋ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค.
์ด๋ ๊ฒ ๊ธฐ์ค ๋ฐ์ ์๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ์๊ฐํด๋๋ฆด๊ฒ์.
๋ฐฉ๋ฒ | ๊ตฌ์ฒด์ ์ธ ํด๊ฒฐ๋ฒ | ์์ |
โ ์๋ ๊ฐ ์ ๊ฑฐํ๊ธฐ | ์๋ ๋ฐ์ดํฐ null ๊ฐ์ผ๋ก ๋ฐํํ๊ธฐ IF (์ปฌ๋ผ๋ช <> 'no data', ์ปฌ๋ผ๋ช , NULL) |
select gender, avg(if (age <> 'nodata', age, null)) avg_age from user_info group by 1 |
NULL ๊ฐ ์์ฒด๋ฅผ ์ ์ธํ๊ธฐ WEHRE ์ปฌ๋ผ๋ช IS NOT NULL |
select name, age, gender from user_info where age is not null |
|
โก ๋ค๋ฅธ ๊ฐ์ผ๋ก ๋์ฒดํ๊ธฐ | NULL ๊ฐ์ ๋ค๋ฅธ ๋ฐ์ดํฐ ๋ฃ๊ธฐ COALESCE (์ปฌ๋ผ๋ช , ๋์ฒด๊ฐ) |
select name, price, coalresce (age, 20) 'null์ ๋์ฒดํ ๋์ด' from user_info |
โข ๋น์์์ ๊ฐ ํด๊ฒฐํ๊ธฐ | ์กฐ๊ฑด๋ฌธ์ ํ์ฉํ ๊ธฐ์ค ๋ฒ์ ์ง์ CASE WHEN ๊ธฐ์ค THEN ๊ฒฐ๊ณผ๊ฐ ...END |
select name, case when age < 15 then 15 when age > 80 then 80 else age end '๋ฒ์๋ฅผ ์ง์ ํด์ค ๋์ด' from user_info |
* <> ๋ '๊ฐ์ง ์๋ค'๋ผ๋ ๋ป์ ๋๋ค.
* 1-1๋ฒ ํด๊ฒฐ๋ฐฉ๋ฒ์ ์ฐ์ฐํ ๋ ๋ง์ด ์ฌ์ฉํ๋ค๊ณ ํฉ๋๋ค.
My sql์ ์ฐ์ฐ์ ์ฌ์ฉํ ์ ์๋ ๊ฐ์ 0์ผ๋ก ๊ฐ์ฃผํ๊ธฐ ๋๋ฌธ์ null๋ก ์ฐ์ฐ์์ ์ ์ธํด ์ฃผ๋ ค๊ณ ์!
2. SQL ํผ๋ฒ ํ ์ด๋ธ(Pivot Table) ์ ์ํ๊ธฐ
์์ ์์ ์์ฃผ ์ฌ์ฉํ๋ ํผ๋ฒ ํ ์ด๋ธ, SQL์์๋ ๋ง๋ค ์ ์์ต๋๋ค!
ํผ๋ฒ ํ ์ด๋ธ์ 2๊ฐ ์ด์์ ๊ธฐ์ค์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ง๊ณํ ๋ ๋ณด๊ธฐ ์ฝ๊ฒ ๋ฐฐ์ดํ์ฌ ๋ณด์ฌ์ฃผ๋ ๊ฒ์ธ๋ฐ์.
์ด(์ธ๋ก)์๋ ์ง๊ณ ๊ธฐ์ค์ด, ํ(๊ฐ๋ก)์๋ ๊ตฌ๋ถ ์ปฌ๋ผ์ด ๋ค์ด๊ฐ๋ ํํ์ ๋๋ค. ๊ธ๋ก ์ฐ์ฌ์์ผ๋๊น, ์ดํดํ๊ธฐ ์ด๋ ต์ฃ ?
์๋ ์ ๊ฐ ๊ฐ์ ์ค์ต์์ ์งฐ๋ ์ฟผ๋ฆฌ๋ฅผ ์๊ฐ๋๋ฆฌ๋ฉฐ, ์ด๋ป๊ฒ ๋ง๋๋์ง ์๋ ค๋๋ฆด๊ฒ์!
โ๏ธ ํผ๋ฒ ํ ์ด๋ธ์ ๋ง๋๋ ์์
- โ ๋ฒ ์ด์ค ๋ฐ์ดํฐ ๋ง๋ค๊ธฐ
- โก ํผ๋ฒ ๋ทฐ ์ ์ํด ์ฃผ๊ธฐ
์ ์์์ ๋ง์ถฐ [์ฑ๋ณ, ๋์ด๋ณ ์ฃผ๋ฌธ๊ฑด์๋ฅผ ์ง๊ณํ ํผ๋ฒ ํ ์ด๋ธ]์ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค! (*10~59์ธ ์ฌ์ด๋ง ์ง๊ณ)
โ ํผ๋ฒ ํ ์ด๋ธ ์์ ๋ค์ด๊ฐ๋ ๋ฒ ์ด์ค ๋ฐ์ดํฐ๋ฅผ ๋ง๋ค์ด์ฃผ๊ฒ ์ต๋๋ค.
-- step 1. ๋ฒ ์ด์ค ๋ฐ์ดํฐ ์ ์ํ๊ธฐ
-- 1) ๋ค๋ฅธ ํ
์ด๋ธ์ ์๋ ๋ฐ์ดํฐ๋ฅผ ์กฐํํ๊ธฐ ์ํ jion ์ฌ์ฉ
-- 2) ์ฑ๋ณ, ์ฃผ๋ฌธ๊ฑด์(count()), ์ฐ๋ น๋๋ณ๋ก ๊ตฌ๊ฐ ๋๋๊ธฐ
-- 3) 10~59์ธ๋ก ์กฐ๊ฑด ์ฃผ๊ธฐ where, ๊ทธ๋ฃน๋ณ์ ๋ง์ถฐ ๋ฐ์ดํฐ ์ง๊ณํ๊ธฐ group by
SELECT c.gender as gender,
count(*) as cnt_orders,
case when c.age between 10 and 19 then 10
when c.age between 20 and 29 then 20
when c.age between 30 and 39 then 30
when c.age between 40 and 49 then 40
when c.age between 50 and 59 then 50 end age
FROM food_orders f inner join customers c on f.customer_id = c.customer_id
WHERE c.age BETWEEN 10 and 59
group by 1,3
โก ๋ฒ ์ด์ค ๋ฐ์ดํฐ๋ ์๋ธ ์ฟผ๋ฆฌ๋ก ๋ฃ์ด์ฃผ๊ณ , ์ด์ ํผ๋ฒ ๋ทฐ๋ฅผ ๋ง๋ค์ด๋ณผ๊ฒ์.
-- STEP 2. ํผ๋ฒ๋ทฐ ๋ง๋ค์ด์ฃผ๊ธฐ
-- 1) ๊ฐ์ฅ ์ฒซ๋ฒ์งธ ์ปฌ๋ผ = ํ ๋ฐ์ดํฐ, ๊ทธ ์ธ๋ ์ด ๋ฐ์ดํฐ๊ฐ ๋ฉ๋๋ค.
-- 2) ์ค์ํ ๊ฒ์ ์ด ๋ฐ์ดํฐ๋ max()๋ก ๊ฐ์ธ์ค์ผ ํฉ๋๋ค.
SELECT gender,
max(if(age = 10, cnt_orders, 0)) '10๋',
max(if(age = 20, cnt_orders, 0)) '20๋',
max(if(age = 30, cnt_orders, 0)) '30๋',
max(if(age = 40, cnt_orders, 0)) '40๋',
max(if(age = 50, cnt_orders, 0)) '50๋'
FROM
(SELECT c.gender as gender,
count(*) as cnt_orders,
case when c.age between 10 and 19 then 10
when c.age between 20 and 29 then 20
when c.age between 30 and 39 then 30
when c.age between 40 and 49 then 40
when c.age between 50 and 59 then 50 end age
FROM food_orders f inner join customers c on f.customer_id = c.customer_id
WHERE c.age BETWEEN 10 and 59
group by 1,3)a
๊ทธ๋ผ ์๋์ ๊ฐ์ ํผ๋ฒ ํ ์ด๋ธ์ ์ป์ผ์ค ์ ์์ต๋๋ค.
์ด์ ์์ ์๊ฐํ์ง๋ง ํ์ ๋์ด๋๋ก ๊ตฌ๋ถํ์ด๋ ๊ด์ฐฎ์์ ๊ฒ ๊ฐ๋ค์.
3. ์๋์ฐ ํจ์ Window function (rank, sum ํ์ฉ)
์๋์ฐ ํจ์(Window function)๋ ๊ด๋ จ ํ์ ๊ทธ๋ฃน ์ฐ์ฐ์ ์ฉ์ดํ๊ฒ ํ๋ ํจ์๋ก
๋ฐ์ดํฐ ๋ถ์, ์ง๊ณ, ์์ ๋งค๊ธฐ๋ ๋ฑ์ ์์ ์ ์ํํ ๋ ์ฌ์ฉํฉ๋๋ค.
group by ์ ์ ์ด์ ๊ธฐ์ค์ผ๋ก ์ฌ๋ฌ ํ์ ๋ฐ์ดํฐ๋ฅผ ํ ๋ฒ์ ์ง๊ณํ์ฌ ๋ณด์ฌ์ค๋ค๋ฉด,
์๋์ฐ ํจ์๋ ์ ์ํ ๊ทธ๋ฃน ๊ธฐ์ค(๋ฒ์)์ ๋ฐ๋ฅธ ์ง๊ณ ๋ฐ์ดํฐ๋ฅผ ๋ณผ ์ ์์ด์.
์๋์ฐํ๋ฉด ์๊ฐ๋๋ ์ฐฝ๋ฌธ๐ช๊ณผ ๊ฐ์ด ๊ฐ ๊ทธ๋ฃน์ ์ฐ์ฐ์ ์ํํ๋ค๊ณ ์ดํดํด ์ฃผ์๋ฉด ๋ฉ๋๋ค!
์๋์ฐ ํจ์ ์ฌ์ฉ๋ฒ์ ์๋์ ๊ฐ๊ณ ์. ๋ฌด์กฐ๊ฑด over() ์ ์์ ์ง์ด ์ฃผ์ ์ผ ํด์.
-- ์๋์ฐ ํจ์ ์ฌ์ฉ๋ฒ
ํจ์() OVER (PARTITION BY ๊ทธ๋ฃน ๊ธฐ์ค ์ปฌ๋ผ ORDER BY ์ ๋ ฌ ๊ธฐ์ค ์ปฌ๋ผ)
์๋์ฐ ํจ์์ ์ข ๋ฅ๋ SUM(), MAX(), RANK(), LAG() ๋ฑ ๋งค์ฐ ๋ค์ํ๋ฐ์,
์ด ์ค ๋ง์ด ํ์ฉํ๋ SUM()๊ณผ RANK() ์์ ๋ฅผ ํตํด ์ด๋ค ์์ผ๋ก ์ฌ์ฉ๋๋์ง ์๊ฐํด๋๋ฆด๊ฒ์.
์ด๋ค ์์๋ก ์ฟผ๋ฆฌ๋ฅผ ์งฐ๋์ง๋ ์ฝ๋ ๋ธ๋ญ ์์ ํจ๊ป ์ ๋ฆฌํด ๋์์ต๋๋ค!
โ N๋ฒ์งธ๊น์ง ๋์์ ์กฐํํ๊ณ ์ถ์ ๋ - Rank
-- ์์ ํ์
๋ณ๋ก, ์ค๋น ๋ฐ ๋ฐฐ๋ฌ ํ๊ท ์๊ฐ์ด ๊ฐ์ฅ ๋น ๋ฅธ ์์ 1~3์์๋ฅผ ๋ฝ์๋ณด์!
-- 1) ๋ฒ ์ด์ค ๋ฐ์ดํฐ ์ ์ : ์์ํ์
, ์์์ , ํ๊ท ์ ์ ์๊ฐ
-- 2) ์์ ํ์
์ ๋ฐ๋ผ ํ๊ท ์ ์์๊ฐ์ด ์ ์ ๊ฒ์ ์์ ๋งค๊ธฐ๊ธฐ rank() over()
-- 3) ์ต์ข
์ ์ผ๋ก where ์ ์ ํ์ฉํ์ฌ 3์์ ์ด๋ด์ ๋ฐ์ดํฐ๋ง ์กฐํํ๊ธฐ
SELECT cuisine_type,restaurant_name, time_rank, avg_time
from (
SELECT cuisine_type,restaurant_name,
rank() over (partition by cuisine_type order by avg_time) as time_rank,
avg_time
from(
select cuisine_type, restaurant_name,
avg(food_preparation_time+delivery_time) as avg_time
from food_orders
group by 1, 2)a )b
WHERE time_rank <= 3
โก ์ ์ฒด์์ ์ฐจ์งํ๋ ๋น์จ, ๋์ ํฉ์ ๊ตฌํ๊ณ ์ถ์ ๋ - Sum
sum ์ ํฉ๊ณ๋ฅผ ๊ตฌํ๋ ํจ์์ง๋ง, ๋์ ํฉ์ด๋ ์นดํ ๊ณ ๋ฆฌ๋ณ ํฉ๊ณ๋ฅผ ๊ตฌํ๊ณ ์ ํ ๋ ์๋์ฐ ํจ์ ํํ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
-- ์์ํ์
๋ณ, ์์์ ๋ณ ๋งค์ถ ์ง๊ณํ๊ณ , ๋์ ๋งค์ถํฉ ๊ตฌํด๋ณด๊ธฐ
-- 1) ๋ฐ์ดํฐ ๋ฒ ์ด์ค ์ ์ : ์์ ํ์
, ์์์ , ๋งค์ถ sum(price * quantity) - group by
-- 2) ๋์ ํฉ๊ณ ์ง๊ณํด๋ณด๊ธฐ sum() over() *์ ๋ ฌ๊ธฐ์ค์ ์ค์ ํ ๋ ๋์ ํฉ์ ๊ตฌํ ์ ์์.
SELECT cuisine_type '์์ ํ์
',
restaurant_name '๋งค์ฅ๋ช
',
rev '๋งค์ฅ ๋งค์ถ',
sum(rev)over(partition by cuisine_type) '์์ ํ์
๋ณ ์ด๋งค์ถ',
sum(rev)over(partition by cuisine_type order by rev, restaurant_name) '์์ ํ์
๋ณ ๋์ ๋งค์ถ'
FROM
(SELECT cuisine_type,
restaurant_name,
sum(price*quantity) as rev
FROM food_orders
GROUP BY 1, 2) a
sum() over()์ ์ ๋ ฌ ๊ธฐ์ค ์ ์ฉํ๋ฉด ๋์ ํฉ์ ๊ตฌํ ์ ์๋๋ฐ์! ์ ๋ ฌ์ ์ ์ฉํ์ง ์์ผ๋ฉด ํ์ ๋ณ ์ด๋งค์ถ์ ์ง๊ณํฉ๋๋ค. ์๋ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ ์ด๋ฏธ์ง๋ฅผ ์ฒจ๋ถํด ๋๋ฆด๊ฒ์. ์ฐธ๊ณ ํ์๋ฉด ์ด๋ป๊ฒ ๊ฒฐ๊ณผ๊ฐ ๋์๋์ง ์ดํดํ์ค ์ ์์ ๊ฑฐ์์!
์ค๋์ ๊ณต๋ถ๋ ์ฌ๊ธฐ๊น์ง ์ ๋๋ค.
๐ฅ๋.๋.์ด [ ์์ ๋ณด๋ค ์ฌ์ด SQL ] ๊ฐ์๋ฅผ ์๊ฐํ์ต๋๋ค๐ฅ
ํ์คํ ๋ง์ง๋ง ์ฑํฐ์ด๋ค ๋ณด๋ ์ด์ ๋ด์ฉ๋ณด๋ค ํจ์ฌ ์ด๋ ต๋ค์.
์ค๋ ๋ธ๋ก๊ทธ๋ฅผ ์์ฑํ๋ฉฐ ๋ณต์ตํ์ง๋ง ์ฌ์ ํ ๊ณต๋ถ๊ฐ ๋ ํ์ํ ๊ฐ๋ ์ด๋ผ๊ณ ์๊ฐ๋ฉ๋๋ค.
์ฃผ๋ง์ ํ๋ฒ ๋ ๊ฐ์๋ฅผ ๋๋ ค๋ด์ผ ํ ๊ฒ ๊ฐ์์! ์ด์ ๋ ์๋ธ ์ฟผ๋ฆฌ๊ฐ ์ด๋ ค์ ์ง๋ง, ์๋์ฐ ํจ์๋ ํผ๋ฒ ํ ์ด๋ธ ๋ฑ ๋ ์ด๋ ค์ด ๊ฐ๋ ์ด ์๊ธฐ๋ ์๋ธ์ฟผ๋ฆฌ๋ ์๋์ ์ผ๋ก ์ฝ๊ณ ๊ท์ฌ์ด ๊ฐ๋ ์ด ๋์๋ค์ ๐
์ ๋ ์ฒ์์ ๊ธฐ์ด ๊ฐ์๋ฅผ ์๊ฐํ๋ฉด์ '๋์ฒด ์ด๋ ๊ฒ ์ถ์ถํ ๋ฐ์ดํฐ๋ฅผ ์ด๋ป๊ฒ ์ค๋ฌด์ ์ ์ฉํ๋ค๋ ๊ฑฐ์ง?' ๋ง์ ๊ณ ๋ฏผ์ด ๋์์ต๋๋ค. ์ฟผ๋ฆฌ๋ฅผ ์ง์ ๋ฐ์ดํฐ๋ฅผ ์ง๊ณํ๋ ๊ฒ๋ ํ๋ค์ง๋ง, ์ด๊ฑธ ๋์ฒด ์ด๋ป๊ฒ ํ์ฉํ ์ ์์์ง ์์์ด ๋์ง ์์๊ฑฐ๋ ์. ๊ทธ๋ฐ๋ฐ ์ค๋ ๋ค๋ฅธ ๋ถ๋ค์ด ์งํํ ๋ฐ์ดํฐ ๋ถ์ ํ๋ก์ ํธ๋ฅผ ๋ณด๋ฉด์, ์ด ์คํฌ์ ์์ผ๋ก ์ด๋ป๊ฒ ์ค๋ฌด์ ์ ์ฉํ ์ ์์์ง ๊ฐ์ด ์กํ๊ธฐ ์์ํ์ต๋๋ค! ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ, ๋ถ์์ ํ ๋๋ก ๋น์ฆ๋์ค์ ์ ์ฉํ ์ ์๋ ๋ด์ฉ์ ๋์ถํ ํ๋ก์ ํธ์๊ฑฐ๋ ์!
๊ฐ์๋ฅผ ๋ค์ผ๋ฉด์ ์๊ฐํ๋ ๊ฒ์ 'ํ์ํ ๋ฐ์ดํฐ๋ฅผ ๋ช ํํ ์ ์ ๋ฐ ์ง๊ณํ๊ณ , ๊ฐ๊ณตํด์ ์ ์๋ฏธํ ์ธ์ฌ์ดํธ๋ฅผ ๋์ถํ๋ ๊ฒ ๊ฐ์ฅ ์ค์ํ๋ค'๋ผ๊ณ ๋๋๋๋ค. ์ง๊ธ์ ๊ฐ์ฌ๋์ด ์ด๋ค ๋ฐ์ดํฐ๋ฅผ ์ด๋ค ํํ๋ก ์ถ์ถํด ๋ณด๋ผ๊ณ ๋ช ํํ ์๋ดํด ์ฃผ์์ง๋ง, ์ค๋ฌด์์๋ ๊ทธ ์ญํ ๋ํ ์ค์ค๋ก ํด์ผ ํ ์ผ์ด ๋ ํ ๋๊น์!
ํ๋ฃจ๊ฐ ๋ค๋ฅด๊ฒ SQL ๋์ด๋๊ฐ ๊ธ์ฆ๊ฐ ํ๋ค๊ณ ๋๋ผ๋ ์์ฆ์ ๋๋ค.
ํ์ง๋ง ์ด์ ๋ ์๋ธ์ฟผ๋ฆฌ๊ฐ ์ด๋ ค์ ์ง๋ง ์ค๋์ ์๋์ฐ ํจ์๊ฐ ์ ์ผ ์ด๋ ค์์ง ๊ฒ์ฒ๋ผ,
๋ ์ด๋ ค์ด ์์ ๊ฐ๋ ์ผ๋ก '์ด๊ฑด ์์ง ์ด๋ ค์ด๊ฒ ์๋๋๋ค^^' ์ ์์ฌ๊ฐ๋ฉฐ
์ด๋ ต๊ฒ๋ง ๋๊ปด์ง๋ SQL์ ์ ์ ๋ณตํด๋ณด๊ณ ์ถ์ต๋๋ค! SQL ๊ณต๋ถํ์๋ ๋ชจ๋ ๋ถ๋ค ํ์ดํ ํ์ธ์๐
*<์์ ๋ณด๋ค ์ฌ์ด SQL> ์จ๋ผ์ธ ๊ฐ์ 5์ฃผ ์ฐจ ์๋ฐ์ ํ์ต ๋ ธํธ์ ๋๋ค.