SQL์์ ์๋์ฐ ํจ์๋ ๋ฐ์ดํฐ๋ฅผ ์ง๊ณํ์ง ์๊ณ ํ์ฌ ํ๊ณผ ๊ด๋ จ๋ ํ ์งํฉ์ ๋ํด ๊ณ์ฐ์ ์ํํฉ๋๋ค.
๋ถ์ธ ์ฑ๋ช ํ๊ตญ์ด ์ค๋ ฅ์ด ๋ถ์ ํ์ฌ ์ด ๊ธ์ด ๊ตฌ๊ธ ๋ฒ์ญ๊ธฐ๋ฅผ ์ฃผ๋ก ํ์ฉํ๊ธฐ ๋๋ฌธ์ ๋ถ์ ํํ ๋ฌธ๋ฒ๊ณผ ์ดํ๊ฐ ์์์ ์์ต๋๋ค. ์ด ์ ์ํด ๋ถํ๋๋ฆฌ๋ฉฐ, ์ถํ์ ๋ค์ ๊ฒํ ํ์ฌ ์์ ํ๋๋ก ํ๊ฒ ์ต๋๋ค.
AVG, MIN ๋ฐ MAX
๋ค์์ AVG, MIN, MAX๋ฅผ ์ฌ์ฉํ ๋ช ๊ฐ์ง ๊ฐ๋จํ ์์
๋๋ค.
SELECT
id,
name,
category,
AVG(price) OVER(),
MIN(price) OVER(),
MAX(price) OVER()
FROM books;์ถ๋ ฅ์ ๋์ผํ ๊ฐ์ ๊ฐ๋ ์ธ ๊ฐ์ ์๋ก์ด ์ด๋ก ๊ตฌ์ฑ๋ฉ๋๋ค.
| id | name | category | avg(price) | min(price) | max(price) |
|---|---|---|---|---|---|
| 1 | book1 | motivation | 50.10 | 5.20 | 120.90 |
| 2 | book2 | motivation | 50.10 | 5.20 | 120.90 |
| 3 | book3 | health | 50.10 | 5.20 | 120.90 |
ํ๊ท ๊ฐ๊ฒฉ์์ ๊ฐ๊ฒฉ ์ฐจ์ด๋ฅผ ๊ณ์ฐ
๋ค์์ผ๋ก, OVER๋ฅผ ์ด์ฉํด ๊ฐ๊ฒฉ ์ฐจ์ด์ ๋ฐฑ๋ถ์จ์ ๊ณ์ฐํ ์ ์์ต๋๋ค.
SELECT
id,
name,
category,
ROUND(AVG(price) OVER(), 2),
ROUND((price - AVG(price) OVER()), 2) AS diff_avg,
ROUND(ABS(price - AVG(price) OVER()) / (AVG(price) OVER() * 100)) AS pct_diff_avg
FROM books;๊ฒฐ๊ณผ๋ ์๋์ ํ์๋ ๊ฒ๊ณผ ๊ฐ์ต๋๋ค.
| id | name | category | avg(price) | diff_avg | pct_diff_avg |
|---|---|---|---|---|---|
| 1 | book1 | motivation | 50.10 | -20.10 | xx |
| 2 | book2 | motivation | 50.10 | 5.60 | xx |
| 3 | book3 | health | 50.10 | 10.80 | xx |
ํํฐ์ ๋
PARTITION BY๋ GROUPBY์ ๋งค์ฐ ์ ์ฌํ์ง๋ง, ๋ถํ ์ OVER() ์ ๋ด์์ ์ํ๋ฉ๋๋ค.
์นดํ ๊ณ ๋ฆฌ๋ณ ํํฐ์
SELECT
id,
name,
category,
publisher,
AVG(price) OVER(PARTITION BY category) AS avg_cat,
AVG(price) OVER(PARTITION BY category, publisher) AS avg_cat_pub
FROM books;์๋์ ์ ์ฌํ ๊ฒฐ๊ณผ๊ฐ ์์ฑ๋ฉ๋๋ค.
| id | name | category | publisher | avg_cat | avg_cat_pub |
|---|---|---|---|---|---|
| 1 | book1 | motivation | pelangi | 30.00 | 32.00 |
| 2 | book2 | motivation | popular | 30.00 | 25.00 |
| 3 | book3 | health | pelangi | 20.80 | 20.80 |
| 4 | book4 | motivation | popular | 30.00 | 25.00 |
| 5 | book5 | health | pelangi | 20.80 | 20.80 |
์ฒซ ๋ฒ์งธ ํํฐ์
์ category ์ด์ ๊ธฐ์ค์ผ๋ก ๊ณ์ฐ์ ์ํํฉ๋๋ค. ๋์ผํ category์ ์ํ๋ ๊ฐ ์ฑ
์ ๋์ผํ ๊ฐ์ ๊ฐ์ ธ์ผ ํฉ๋๋ค. ๋ ๋ฒ์งธ ํํฐ์
์ category ์ด๊ณผ publisher ์ด์ ์ฌ์ฉํ์ฌ ๊ณ์ฐ์ ์ํํฉ๋๋ค. ๋์ผํ category์ publisher์ ์ํ๋ ์ฌ๋๋ค๋ ๋์ผํ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ๊ฒ์ผ๋ก ์์๋ฉ๋๋ค.
์์
Row Number
์์๋ ์ฐฝ ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์ํ๋ ์ด์ ๊ธฐ์ค์ผ๋ก ๊ณ์ฐ๋ ์ ์์ต๋๋ค.
SELECT
id,
name,
category,
price,
ROW_NUMBER() OVER(ORDER BY price DESC) AS rank_by_price
FROM books;| id | name | category | price | rank_by_price |
|---|---|---|---|---|
| 1 | book1 | motivation | 99.99 | 1 |
| 2 | book2 | motivation | 70.00 | 2 |
| 3 | book3 | health | 30.50 | 3 |
| 4 | book4 | motivation | 10.00 | 4 |
| 5 | book5 | health | 5.80 | 5 |
ํ๋ ์ค๋ฆ์ฐจ์์ผ๋ก ์ป์ ์์์ ๋ฐ๋ผ ํ์ ๋์ดํฉ๋๋ค.
๋ํ, ์์๋ฅผ ์ด, ์๋ฅผ ๋ค์ด category์ ๋ฐ๋ผ ๋ถํ ํ ์ ์์ต๋๋ค.
SELECT
id,
name,
category,
price,
ROW_NUMBER() OVER(PARTITION BY category ORDER BY price DESC) AS rank_partition_by_price
FROM books;์ด์ ๊ฒฐ๊ณผ๋ ์์ฒด ํํฐ์ ๋ด์ ํ์ ์์๋ฅผ ๋งค๊น๋๋ค.
| id | name | category | price | rank_partition_by_price |
|---|---|---|---|---|
| 1 | book1 | motivation | 99.99 | 1 |
| 2 | book2 | motivation | 70.00 | 2 |
| 3 | book3 | health | 30.50 | 1 |
| 4 | book5 | health | 10.00 | 2 |
| 5 | book4 | motivation | 5.80 | 1 |
๋ฌธ์ ์ง์ : ์ฑ ์ด ์นดํ ๊ณ ๋ฆฌ๋ณ ์์ 3์์ด๋ฉด "์", ๊ทธ๋ ์ง ์์ผ๋ฉด "์๋์"๋ก ์ด์ ์ฑ์ฐ๋ ์ ์ด์ ๋ง๋ญ๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด CASE ๋ฌธ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
SELECT
id,
name,
category,
price,
CASE
WHEN ROW_NUMBER() OVER(PARTITION BY category ORDER BY price DESC) <= 3 THEN 'Yes'
ELSE 'No'
END AS top3_of_category
FROM books;๊ฒฐ๊ณผ๊ฐ ๋ค์๊ณผ ๋น์ทํ ๊ฒ์ ๋๋ค.
| id | name | category | price | top3_of_category |
|---|---|---|---|---|
| 1 | book1 | motivation | 99.99 | Yes |
| 2 | book2 | motivation | 70.00 | Yes |
| 3 | book3 | motivation | 30.50 | Yes |
| 4 | book5 | motivation | 10.00 | No |
| 5 | book4 | motivation | 5.80 | No |
| 6 | book6 | health | 100.00 | Yes |
Rank ๋ฐ Dense Rank
Rank์ dense rank๋ ROW_NUMBER๊ฐ ์๋ํ๋ ๋ฐฉ์๊ณผ ๋งค์ฐ ์ ์ฌํ์ง๋ง ๋ฏธ๋ฌํจ์ด ์์ต๋๋ค. ๋์ ์ด์ ๋ํด ์ ํํ ๋์ผํ ๊ฐ์ ๊ฐ์ง ๋ ์ฝ๋๋ฅผ ์์๋ฅผ ๋งค๊ธฐ๋ ๋ฐ ์ ์ฉํฉ๋๋ค.
SELECT
id,
name,
category,
price,
RANK() OVER(PARTITION BY category ORDER BY price DESC) AS rank_partition_by_price
FROM books;| id | name | category | price | rank_partition_by_price |
|---|---|---|---|---|
| 1 | book1 | motivation | 99.99 | 1 |
| 2 | book2 | motivation | 70.00 | 2 |
| 3 | book3 | motivation | 70.00 | 2 |
| 4 | book5 | motivation | 60.50 | 4 |
| 5 | book4 | motivation | 60.50 | 4 |
| 6 | book6 | motivation | 30.00 | 6 |
๋์ผํ ๋ ์ฝ๋์ ์์๋ ๋์ผํ์ง๋ง, ํ์ ์์๋ ๋์ผํ ๊ฐ์ ๊ฐ๋ ๋ ์ฝ๋์ ์์ ๋ฐ๋ผ ๊ฑด๋๋๋๋ค.
๋ฐ๋ฉด, ๋ฐ์ง ์์๋ ์์ ์์๋ฅผ ๋ณด์กดํ๊ณ ํ์ ์์๋ฅผ ๊ฑด๋๋ฐ์ง ์์ต๋๋ค.
์๋๋ ๋์ผํ ์ฟผ๋ฆฌ์์ RANK ํค์๋๋ฅผ DENSE_RANK๋ก ๋์ฒดํ์ ๋ ์ป์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ค๋๋ค.
| id | name | category | price | rank_partition_by_price |
|---|---|---|---|---|
| 1 | book1 | motivation | 99.99 | 1 |
| 2 | book2 | motivation | 70.00 | 2 |
| 3 | book3 | motivation | 70.00 | 2 |
| 4 | book5 | motivation | 60.50 | 3 |
| 5 | book4 | motivation | 60.50 | 3 |
| 6 | book6 | motivation | 30.00 | 4 |
Lag ๋ฐ Lead
- Lag - ์์ ๋ด์์ ์ด์ ๊ฐ์ ๊ฐ์ ธ์ต๋๋ค
- Lead - ์์ ๋ด์์ ๋ค์ ๊ฐ์ ๊ฐ์ ธ์ต๋๋ค
SELECT
id,
name,
category,
price,
LAG(price) OVER(PARTITION BY category ORDER BY price) a,
LEAD(price) OVER(PARTITION BY category ORDER BY price) b
FROM books;์ ์ฟผ๋ฆฌ๋ฅผ ์คํํ๋ฉด ์๋ ํ์ ํ์๋ ๊ฒฐ๊ณผ๊ฐ ์์ฑ๋ฉ๋๋ค.
| id | name | category | price | a | b |
|---|---|---|---|---|---|
| 1 | book1 | motivation | 99.99 | null | 70.00 |
| 2 | book2 | motivation | 70.00 | 99.99 | 70.00 |
| 3 | book3 | motivation | 70.00 | 70.00 | 60.50 |
| 4 | book5 | motivation | 60.50 | 70.00 | 60.50 |
| 5 | book4 | motivation | 60.50 | 60.50 | 30.00 |
| 6 | book6 | motivation | 30.00 | 60.50 | null |
lag์ lead๋ ๋ ๋ค ์ฌ์ฉํ ๊ธฐ๊ฐ์ ์ง์ํ๋ ์ถ๊ฐ์ ์ธ ์ ํ์ ๋งค๊ฐ๋ณ์๋ฅผ ํ์ฉํฉ๋๋ค.
LAG(price, 2)
LEAD(price, 5)์ฌ์ฉ ์๋๋ฆฌ์ค
์๋์ฐ ํจ์์ ๋ช ๊ฐ์ง ์ฌ์ฉ๋ฒ
- ์์
- ์ด๋ ํ๊ท
- ๋์ (๋์ )
- ๊ธฐ๊ฐ๋ณ ๋น๊ต
- ๋ฐฑ๋ถ์์ ๊ณ์ฐ
- ์์๊ฐ์ ๋ง๊ฐ๊ฐ
- ์๊ณ์ด ๋ถ์