ํฐ์คํ ๋ฆฌ ๋ทฐ
[๋ฐ์ดํฐ ๋ถ์์ ์ํ SQL ๋ ์ํผ] 7์ฅ. ํ๋์ ํ ์ด๋ธ์ ๋ํ ์กฐ์
์คํฑ 2023. 9. 10. 21:54๐ก ๋๊ท๋ชจ์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ์, ๊ฐ ๋ ์ฝ๋ ํ๋ํ๋๋ฅผ ๋ค๋ฃจ๊ธฐ๋ ์ฝ์ง ์์
→ ๋๋์ ๋ฐ์ดํฐ๋ฅผ ์ง๊ณํ๊ณ ๋ช๊ฐ์ง ์งํ๋ฅผ ์ฌ์ฉํด ๋ฐ์ดํฐ ์ ์ฒด์ ํน์ง ํ์ ํ๊ธฐ!
- ๋ฐ์ดํฐ ์ง์ฝ : ํ๊ท , ์ต๋ ์ต์,,, ํต๊ณ ์งํ ์ถ๋ ฅ → ์๋ ํจ์๋ฅผ ์ฌ์ฉํด ์์๋ฅผ ๊ณ ๋ คํ๋ ์ฒ๋ฆฌ, ์ฌ๋ฌ๊ฐ์ ๋ ์ฝ๋๋ฅผ ๋์์ผ๋ก ํ๋ ์ฒ๋ฆฌ
- ๋ฐ์ดํฐ ๊ฐ๊ณต : ํ ์ด๋ธ ํ์์ด ์ง๊ณ์ ์ ํฉํ์ง ์์ ๊ฒฝ์ฐ ์ด๋ป๊ฒ ํ ์ด๋ธ์ ๊ฐ๊ณตํด์ผ ํ๋์ง!
1. ๊ทธ๋ฃน์ ํน์ง ์ก๊ธฐ
์ง์ฝ ํจ์ : ์ฌ๋ฌ ๋ ์ฝ๋๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋์ ๊ฐ์ ๋ฆฌํดํ๋ ํจ์
ex) COUNT(), SUM()
ํ ์ด๋ธ ์ ์ฒด์ ํน์ง๋ ๊ณ์ฐํ๊ธฐ
COUNT : ์ง์ ํ ์ปฌ๋ผ์ ๋ ์ฝ๋ ์ ๋ฆฌํด
DISTINCT : ์ค๋ณต์ ์ ์ธํ๊ณ ์๋ฅผ ์ธ์์ค
SELECT
COUNT(*) AS total_count
, COUNT(DISTINCT user_id) AS user_count
, COUNT(DISTINCT product_id) AS product_count
, SUM(score) AS sum, AVG(score) AS avg,MAX(score) AS max,MIN(score) AS min
FROM
review
;
๊ทธ๋ฃจํํ ๋ฐ์ดํฐ์ ํน์ง๋ ๊ณ์ฐ
- GROUP BY ๊ตฌ๋ฌธ์ ์ด์ฉํด ๋ฐ์ดํฐ๋ฅผ ์กฐ๊ธ ๋ ์๊ฒ ๋ถํ
SELECT
user_id,
COUNT(*) AS total_count
, COUNT(DISTINCT user_id) AS user_count
, COUNT(DISTINCT product_id) AS product_count
, SUM(score) AS sum, AVG(score) AS avg,MAX(score) AS max,MIN(score) AS min
FROM
review
GROUP BY user_id
;
โผ๏ธ GROUP BY๋ฅผ ์ฌ์ฉํ์ ๋, SELECT ๊ตฌ๋ฌธ์๋ ์ง์ฝํจ์ ๋๋ Group by๊ตฌ๋ฌธ์ ์ง์ ํ ์ปฌ๋ผ๋ง์ด ์ฌ ์ ์์! ( Group by๋ฅผ ์ฌ์ฉํ๋ฉด ์ง์ ์ปฌ๋ผ์ ์ ๋ํฌ ํค๋ก ์๋ก์ด ํ ์ด๋ธ์ ๋ง๋ค๊ธฐ ๋๋ฌธ!)
์ง์ฝ ํจ์๋ฅผ ์ ์ฉํ ๊ฐ๊ณผ ์ง์ฝ ์ ์ ๊ฐ์ ๋์์ ๋ค๋ฃจ๊ธฐ
์๋ ํจ์๋ฅผ ์ด์ฉํด ์ง์ฝํจ์์ ๊ฒฐ๊ณผ์ ์๋๊ฐ์ ์กฐํฉํ ์ ์์!
๐ก ์๋์ฐ ํจ์๋? : Group By์ ์ ์ฌํ๊ฒ ๋ฐ์ดํฐ๋ฅผ ๊ทธ๋ฃนํํ์ฌ ์ง๊ณํด์ฃผ๋ ํจ์!
but, Group By๋ ์ง๊ณ๋ ๊ฒฐ๊ณผ๋ง ๋ณด์ฌ์ฃผ๋ ๋ฐ๋ฉด, ์๋์ฐ ํจ์๋ ๊ธฐ์กด ๋ฐ์ดํฐ์ ์ง๊ณ๋ ๊ฐ์ ์ถ๊ฐํด์ ๋ํ๋ด์ค๋ค!
# ์๋์ฐ ํจ์ ๊ธฐ๋ณธ ํํ
ํจ์(ํจ์_์ ์ฉ_์ด)OVER (PARTITIONBY ๊ทธ๋ฃน์ด ORDERBY ์์์ด)
PARTITION BY : Group By์ ๊ฐ์ ๊ธฐ๋ฅ
ORDER BY : Order By์ ๊ฐ์ ๊ธฐ๋ฅ (DESC : ๋ด๋ฆผ์ฐจ์)
# ๊ฐ๋ณ ๋ฆฌ๋ทฐ ์ ์์ ์ฌ์ฉ์ ํ๊ท ๋ฆฌ๋ทฐ ์ ์์ ์ฐจ์ด๋ฅผ ๊ตฌํ๊ธฐ
SELECT
user_id, product_id,
-- ๊ฐ๋ณ ๋ฆฌ๋ทฐ ์ ์
score,
-- ์ ์ฒด ํ๊ท ๋ฆฌ๋ทฐ ์ ์
AVG(score) OVER() as avg_score,
-- ์ฌ์ฉ์์ ํ๊ท ๋ฆฌ๋ทฐ ์ ์
AVG(score) OVER(PARTITION BY user_id) AS user_avg_score,
-- ๊ฐ๋ณ ๋ฆฌ๋ทฐ ์ ์์ ์ฌ์ฉ์ ํ๊ท ๋ฆฌ๋ทฐ ์ ์์ ์ฐจ์ด
score - AVG(score) OVER(PARTITION BY user_id) AS user_avg_score_diff
FROM review;
- ์ง์ฝํจ์๋ก ์๋ ํจ์๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด, ์ง์ฝ ํจ์ ๋ค์ OVER ๊ตฌ๋ฌธ์ ๋ถ์ด๊ณ , ์ฌ๊ธฐ์ ์๋ํจ์๋ฅผ ์ง์
- OVER ๊ตฌ๋ฌธ์ ๋งค๊ฐ๋ณ์๋ฅผ ์ง์ ํ์ง ์์ผ๋ฉด ํ ์ด๋ธ ์ ์ฒด์ ์ง์ฝํจ์๋ฅผ ์ ์ฉํ ๊ฐ์ด ๋ฆฌํด๋จ!
- ๋งค๊ฐ๋ณ์์ PARTITION BY <์ปฌ๋ผ ์ด๋ฆ>์ ์ง์ ํ๋ฉด ํด๋น ์ปฌ๋ผ ๊ฐ์ ๊ธฐ๋ฐ์ผ๋ก ๊ทธ๋ฃนํํ๊ณ ์ง์ฝํจ์ ์ ์ฉ
2. ๊ทธ๋ฃน ๋ด๋ถ์ ์์
์๋ํจ์๊ฐ ๋ฑ์ฅํ๋ฉด์, SQL๋ก ์์๋ฅผ ๋ค๋ฃจ๋ ๊ฒ์ด ๊ต์ฅํ ์ฌ์์ง!
ORDER BY ๊ตฌ๋ฌธ์ผ๋ก ์์ ์ ์ํ๊ธฐ
์๋ ํจ์๋, ํ ์ด๋ธ ๋ด๋ถ์ ‘์๋’๋ผ๊ณ ๋ถ๋ฅด๋ ๋ฒ์๋ฅผ ์ง์ ํ๊ณ , ํด๋น ๋ฒ์ ๋ด๋ถ์ ํฌํจ๋ ๊ฐ์ ํน์ ๋ ์ฝ๋์์ ์์ ๋กญ๊ฒ ์ฌ์ฉํ๋ ค๊ณ ๋์ ํ ๊ฒ!
→ ์ด๋, ํด๋น ๊ฐ์ ์์น๋ฅผ ๋ช ํํ๊ฒ ์ง์ ํด์ผํจ
→ OVER๊ตฌ๋ฌธ ๋ด๋ถ์ ORDER BY ๊ตฌ๋ฌธ์ฌ์ฉํ๋ฉด, ์๋ ๋ด๋ถ์ ์๋ ๋ฐ์ดํฐ์ ์์ ์ ์ ๊ฐ๋ฅ!
SELECT
product_id
, score
-- ์ ์ ์์๋ก ์ ์ผํ ์์
, ROW_NUMBER() OVER(ORDER BY score DESC) AS row
-- ๊ฐ์ ์์ ํ์ฉ, ์์
, RANK() OVER(ORDER BY score DESC) AS rank
-- ๊ฐ์ ์์ ํ์ฉ, ์์ ์ซ์๋ ๊ฑด๋๋
, DENSE_RANK() OVER(ORDER BY score DESC) AS dense_rank
-- ํ์ฌ ํ๋ณด๋ค ์์ ์๋ ํ ์ถ์ถ
, LAG(product_id) OVER(ORDER BY score DESC) AS lag1
, LAG(product_id, 2) OVER(ORDER BY score DESC) AS lag2
-- ํ์ฌ ํ๋ณด๋ค ๋ค์ ์๋ ํ ์ถ์ถ
, LEAD(product_id) OVER(ORDER BY score DESC) AS lead1
, LEAD(product_id, 2) OVER(ORDER BY score DESC) AS lead2
FROM popular_products
ORDER BY row
;
- ORDER BY score DESC ๋ก ํ ์ด๋ธ ๋ด๋ถ์ ์ํ์ ์ค์ฝ์ด๊ฐ ๋์ ์์ผ๋ก ์ ๋ ฌ
- ROW_NUMBER : ์์์ ์์๋ฒํธ๋ฅผ ๋ถ์ด๊ธฐ
- RANK ์ DENSE_RANK ํจ์๋, ๊ฐ์ ์์์ ๋ ์ฝ๋๊ฐ ์์ ๋, ๋์ผํ ์์ ๋ฒํธ๋ฅผ ๋ถ์
- RANK์ ๊ฒฝ์ฐ, ๊ฐ์ ์์์ ๋ ์ฝ๋ ๋ค์ ์์ ๋ฒํธ๋ฅผ ๊ฑด๋ ๋
- 1, 1, 3, 4, ...
- DENSE_RANK :์์ ๋ฒํธ๋ฅผ ๊ฑด๋๋ฐ์ง ์์
- 1, 1, 2, 3, ...
- LAG์ LEAD ํจ์๋
- ํ์ฌ ํ์ ๊ธฐ์ค์ผ๋ก ์์ ํ ๋๋ ๋ค์ ํ์ ์ถ์ถํ๋ ํจ์
- ๋๋ฒ์งธ ๋งค๊ฐ๋ณ์์ ์ซ์๋ฅผ ์ง์ ํ์ฌ n๋ฒ์งธ ๊ฐ ์ถ์ถ
ORDER BY ๊ตฌ๋ฌธ๊ณผ ์ง์ฝํจ์ ์กฐํฉํ๊ธฐ
- ORDER BY์ SUM/AVG ๊ฐ์ ์ง์ฝํจ์๋ฅผ ์กฐํฉํ๋ฉด, ์ง์ฝ ํจ์์ ์ ์ฉ ๋ฒ์๋ฅผ ์ ์ฐํ๊ฒ ์ง์ ํ ์ ์์!
# ORDER BY ๊ตฌ๋ฌธ์ ์ด์ด์ง๋ ROWS ๊ตฌ๋ฌธ์ ์๋ ํ๋ ์ ์ง์ ๊ตฌ๋ฌธ ์ฟผ๋ฆฌ
SELECT
product_id
, score
-- ์ ์ ์์๋ก ์ ์ผํ ์์๋ฅผ ๋ถ์
, ROW_NUMBER() OVER(ORDER BY score DESC) AS row
-- ์์ ์์์์ ํ์ฌ ํ๊น์ง์ ์ค์ฝ์ด๋ฅผ ๋ชจ๋ ๋ํ ๊ฐ ๊ณ์ฐ
, SUM(score)
OVER(ORDER BY score DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
AS cum_score
-- ํ์ฌ ํ ๊ธฐ์ค ์ /ํ ์ด 3๊ฐํ์ ํ๊ท ์ ์ ๊ณ์ฐ
, AVG(score)
OVER(ORDER BY score DESC
ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)
AS local_avg
-- FIRST_VALUE : ์์๊ฐ ๋์ ์ํ ID(์๋ ๋ด๋ถ์ ์ฒซ ๋ ์ฝ๋)
, FIRST_VALUE(product_id)
OVER(ORDER BY score DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
AS first_value
-- LAST VALUE : ์์๊ฐ ๋ฎ์ ์ํ ID(์๋ ๋ด๋ถ์ ๋ง์ง๋ง ๋ ์ฝ๋)
, LAST_VALUE(product_id)
OVER(ORDER BY score DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
AS last_value
FROM popular_products
ORDER BY row
;
์๋์ฐ ํ๋ ์ ์ง์
- ํ๋ ์ ์ง์ ์ด๋? ํ์ฌ ๋ ์ฝ๋ ์์น๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์๋์ ์ธ ์๋๋ฅผ ์ ์ํ๋ ๊ตฌ๋ฌธ - 3๊ฐ์ง ์ข ๋ฅ
- ROWS BETWEEEN {start} AND {end}
- start์ end์๋
- CURRENT ROW : ํ์ฌ ํ
- n PRECEDING : nํ ์
- n FOLLOWING : nํ ๋ค
- UNBOUNDED PRECEDING : ์ด์ ํ ์ ๋ถ
- UNBOUNDED FOLLOWING : ์ดํ ํ ์ ๋ถ
- start์ end์๋
- array_agg : ๋ค์์ row๋ค์ ํน์ ์นผ๋ผ๊ฐ์ ํ๋์ ๋ฐฐ์ด์ ๋ด๊ณ ์ถ์ ๋ ์ฌ์ฉํ๋ ํจ์
# ๋ฒ์ ๋ด๋ถ ์ํ ID๋ฅผ ์ง์ฝํ๋ ์ฟผ๋ฆฌ
SELECT
product_id
, ROW_NUMBER() OVER(ORDER BY score DESC) AS row
-- ๊ฐ์ฅ ์ ์์๋ถํฐ, ๋ท ์์๊น์ง์ ๋ฒ์๋ฅผ ๋์์ผ๋ก ์ํ ID ์ง์ฝ
, array_agg(product_id)
OVER(ORDER BY score DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
AS whole_agg
-- ๊ฐ์ฅ ์ ์์๋ถํฐ ํ์ฌ ์์๊น์ง์ ๋ฒ์๋ฅผ ๋์์ผ๋ก ์ํ ID ์ง์ฝ
, array_agg(product_id)
OVER(ORDER BY score DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
AS cum_agg
-- ์์ ํ๋ ์/๋ค๊น์ง์ ๋ฒ์๋ฅผ ๋์์ผ๋ก ์ํ ID ์ง์ฝ
, array_agg(product_id)
OVER(ORDER BY score DESC
ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)
AS local_agg
FROM popular_products
WHERE category='action'
ORDER BY row
;
- ์๋ ํจ์์ ํ๋ ์ ์ง์ ์ ํ์ง ์์ผ๋ฉด, ORDER BY ๊ตฌ๋ฌธ์ด ์๋ ๊ฒฝ์ฐ ๋ชจ๋ ํ, ORDER BY ๊ตฌ๋ฌธ์ด ์๋ ๊ฒฝ์ฐ ์ฒซ ํ์์ ํ์ฌ ํ๊น์ง๊ฐ ๋ํดํธ๋ก ์ง์ !
PARTITION BY์ ORDER BY ์กฐํฉํ๊ธฐ
- PARTITION BY์ ORDER BY ๊ตฌ๋ฌธ์ ์กฐํฉํด ์นดํ ๊ณ ๋ฆฌ๋ค์ ์์๋ฅผ ๊ณ์ฐํ๋ ์ฟผ๋ฆฌ
SELECT
category, product_id, score,
-- ์นดํ
๊ณ ๋ฆฌ ๋ณ๋ก ์ ์ ์์๋ก ์ ๋ ฌํ๊ณ , ์ ์ผํ ์์๋ฅผ ๋ถ์
ROW_NUMBER() OVER (PARTITION BY category ORDER BY score DESC) AS row
-- ์นดํ
๊ณ ๋ฆฌ ๋ณ๋ก ๊ฐ์ ์์๋ฅผ ํ๊ฐํ๊ณ ์์๋ฅผ ๋ถ์
, RANK() OVER (PARTITION BY category ORDER BY score DESC) AS rank
-- ์นดํ
๊ณ ๋ฆฌ๋ณ๋ก ๊ฐ์ ์์๊ฐ ์์ ๋
-- ๊ฐ์ ์์ ๋ค์์ ์๋ ์์๋ฅผ ๊ฑด๋ ๋ฐ๊ณ ์์๋ฅผ ๋ถ์
, DENSE_RANK()
OVER (PARTITION BY category ORDER BY score DESC) AS dense_rank
FROM popular_products ORDER BY category, row;
- ๊ฐ ์นดํ ๊ณ ๋ฆฌ์ ์์ n๊ฐ ์ถ์ถํ๊ธฐ
์๋ํจ์๋ฅผ WHERE๊ตฌ๋ฌธ์ ์์ฑํ ์ ์์
→ ์๋ํจ์๋ฅผ ์ฌ์ฉํ ๊ฒฐ๊ณผ๋ฅผ ์๋ธ์ฟผ๋ฆฌ๋ก ๋ง๋ค๊ณ , WHERE๊ตฌ๋ฌธ ์ ์ฉํ๊ธฐ!
SELECT * FROM
-- ์๋ธ์ฟผ๋ฆฌ ๋ด๋ถ์์ ์์ ๊ณ์ฐํ๊ธฐ
( SELECT category, product_id, score,
-- ์นดํ
๊ณ ๋ฆฌ๋ณ๋ก ์ ์ ์์๋ก ์ ์ผํ ์์๋ฅผ ๋ถ์
ROW_NUMBER() OVER (PARTITION BY category ORDER BY score DESC) AS rank
FROM popular_products
) AS popular_products_with_rank
-- ์ธ๋ถ์ฟผ๋ฆฌ์์ ์์ ํ์ฉํด ์์ถํ๊ธฐ
WHERE rank <= 2 ORDER BY category, rank;
- ๊ฐ ์นดํ ๊ณ ๋ฆฌ๋ณ ์์ ์์์์ ์์ 1๊ฐ์ ์ํ ID๋ง์ ์ถ์ถํ๊ธฐ
→ FIRST_VALUE ์๋์ฐ ํจ์๋ฅผ ์ฌ์ฉํ๊ณ , SELECT DISTINCT ๊ตฌ๋ฌธ์ผ๋ก ๊ฒฐ๊ณผ ์ง์ฝํ๊ธฐ!
-- DISTINCT ๊ตฌ๋ฌธ์ ์ฌ์ฉํด ์ค๋ณต ์ ๊ฑฐํ๊ธฐ!
SELECT DISTINCT category
-- ์นดํ
๊ณ ๋ฆฌ๋ณ๋ก ์์ ์ต์ํ ์ํ ID ์ถ์ถํ๊ธฐ
, FIRST_VALUE(product_id)
OVER (PARTITION BY category ORDER BY score DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS product_id
FROM popular_products;
- DISTINCT ์ ์ธ ๊ฒฝ์ฐ!
3. ์ธ๋ก ๊ธฐ๋ฐ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๋ก ๊ธฐ๋ฐ์ผ๋ก ๋ณํํ๊ธฐ
- ํ ๋จ์๋ก ์ ์ฅ๋ ‘์ธ๋ก ๊ธฐ๋ฐ’์, ์ด ๋๋ ์ผํ๋ก ๊ตฌ๋ถ๋ ๋ฌธ์์ด ๋ฑ์ ‘๊ฐ๋ก๊ธฐ๋ฐ’์ผ๋ก ๋ณํํ๊ธฐ!
- SQL์์ ํ(๋ ์ฝ๋) ๊ธฐ๋ฐ์ผ๋ก ์ฒ๋ฆฌํ๋ ๊ฒ์ด ๊ธฐ๋ณธ์ด๋ฏ๋ก, ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ๋ ์ต๋ํ ๋ฐ์ดํฐ๋ฅผ ํ์ผ๋ก ๋ถํ ํ๋ ๊ฒ์ด ์ข์! but, ์ต์ข ์ถ๋ ฅ์์ ๋ฐ์ดํฐ๋ฅผ ์ด๋ก ์ ๊ฐํด์ผ ๊ฐ๋ ์ฑ์ด ๋์ ๊ฒฝ์ฐ ๋ง๋ค
ํ์ ์ด๋ก ๋ณํํ๊ธฐ
SQL์์ ์ด์ ๊ณ ์ ์ ์ด์ด์ผ ํจ! → ์ด๋ก ์ ๊ฐํ ๋ฐ์ดํฐ์ ์ข ๋ฅ ๋๋ ์๋ฅผ ๋ช ํํ๊ฒ ์๊ณ ์์ด์ผ ํจ!
# ํ์ผ๋ก ์ ์ฅ๋ ์งํ๋ฅผ ์ด๋ก ๋ณํํ๋ ์ฟผ๋ฆฌ
# Group by dt๋ก ๋ ์ง๋ฅผ 1๊ฐ์ ๋ ์ฝ๋๋ก ์ง์ฝํ๊ฒ ํจ!
SELECT dt, MAX(CASE WHEN indicator = 'impressions' THEN val END) AS impressions
, MAX(CASE WHEN indicator = 'sessions' THEN val END) AS sessions,
MAX(CASE WHEN indicator = 'users' THEN val END) AS users
FROM daily_kpi
GROUP BY dt ORDER BY dt;
- ์ด๋, MAX๋ฅผ ์จ์ค ์ด์ -> SELECT ๋ฌธ์ GROUP BY ๋ฌธ์ ์ฌ์ฉ๋ ์ปฌ๋ผ์ด๋ ์ง๊ณํจ์๋ง์ด ๋ค์ด๊ฐ ์ ์๊ธฐ ๋๋ฌธ์!
ํ์ ์ผํ๋ก ๊ตฌ๋ถํ ๋ฌธ์์ด๋ก ์ง์ฝํ๊ธฐ
- ์ด์ ์ข ๋ฅ์ ์๋ฅผ ๋ชจ๋ฅผ ๊ฒฝ์ฐ์๋ ํ์ ์ด๋ก ๋ณํํ๋ ๋ฐฉ๋ฒ์ ์ธ ์ ์์!
ํ๋ฒ์ ์ฃผ๋ฌธ์ผ๋ก ์ฌ๋ฌ๊ฐ์ ์ํ์ ๊ตฌ๋งคํ์ ๋ → ์ด๋ฅผ ์ํ๋ณ๋ก ๋ ์ฝ๋๋ฅผ ๋๋์ด ์ ์ฅํ๋ ํ ์ด๋ธ! ๊ตฌ๋งคid๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ ์ฝ๋๋ฅผ ํ๋๋ก ์ง์ฝํ๊ณ ์ถ์ด๋ ์ํ์ ๋ช ๊ฐ ์ฃผ๋ฌธํ๋์ง ๋ฏธ๋ฆฌ ์ ์ ์์! → ์ด๋ก ์ง๊ณ๊ฐ ์ด๋ ต๋ค!
→ ํ์ ์ง์ฝํด์ ์ผํ๋ก ๊ตฌ๋ถ๋ ๋ฌธ์์ด๋ก ๋ณํํ๊ธฐ! string_agg ํจ์ ์ด์ฉ
SELECT purchase_id
-- ์ํ id๋ฅผ ๋ฐฐ์ด์ ์ง์ฝํ๊ณ ์ผํ๋ก ๊ตฌ๋ถ๋ ๋ฌธ์์ด๋ก ๋ณํํ๊ธฐ
, string_agg(product_id, ',') AS product_ids
, SUM(price) as amount
FROM purchase_detail_log GROUP BY purchase_id ORDER BY purchase_id;
4. ๊ฐ๋ก ๊ธฐ๋ฐ ๋ฐ์ดํฐ๋ฅผ ์ธ๋ก ๊ธฐ๋ฐ์ผ๋ก ๋ณํํ๊ธฐ
- ๊ฐ๋ก ๊ธฐ๋ฐ์ ์ธ๋ก ๊ธฐ๋ฐ์ผ๋ก ๋ณํํ๋ ๊ฒ์ ๊ฐ๋จํ ์ผ์ด ์๋!
- ์ด๋ฏธ ๋ฐ์ดํฐ๊ฐ ์ผํ๋ก ๊ตฌ๋ถ๋ ์ด ๊ธฐ๋ฐ์ ํ์์ผ๋ก ์ ์ฅ๋ ๊ฒฝ์ฐ ๋ง์! → ๋ณํํด์ผํจ!
์ด๋ก ํํ๋ ๊ฐ์ ํ์ผ๋ก ๋ณํํ๊ธฐ
- ์ปฌ๋ผ์ผ๋ก ํํ๋ ๊ฐ๋ก๊ธฐ๋ฐ ๋ฐ์ดํฐ์ ํน์ง : ๋ฐ์ดํฐ์ ์๊ฐ ๊ณ ์ ๋์ด ์๋ค๋ ๊ฒ!
→ ์์ ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ฉด, q1 ~ q4๊น์ง ๋ชจ๋ 4๊ฐ์ ๋ฐ์ดํฐ → ๋ฐ์ดํฐ ์ ๋งํผ์ ์ผ๋ จ๋ฒํธ๋ฅผ ๊ฐ์ง ํผ๋ฒํ ์ด๋ธ์ ๋ง๋ค๊ณ CROSS JOIN ํ๊ธฐ!
# ํผ๋ฒํ
์ด๋ธ์ ๊ฒฐํฉํ๊ณ , CASE ์์ผ๋ก ๋ ์ด๋ธ ์ด๋ฆ๊ณผ ๋งค์ถ๊ฐ์ ์ถ์ถํด์ ์ด์ ํ์ผ๋ก ๋ณํ!
SELECT
q.year,
-- Q1์์ Q4๊น์ง์ ๋ ์ด๋ธ ์ด๋ฆ ์ถ๋ ฅํ๊ธฐ
CASE
WHEN p.idx = 1 THEN 'q1'
WHEN p.idx = 2 THEN 'q2'
WHEN p.idx = 3 THEN 'q3'
WHEN p.idx = 4 THEN 'q4'
END AS quarter
-- Q1์์ Q4๊น์ง์ ๋งค์ถ ์ถ๋ ฅํ๊ธฐ
, CASE
WHEN p.idx = 1 THEN q.q1
WHEN p.idx = 2 THEN q.q2
WHEN p.idx = 3 THEN q.q3
WHEN p.idx = 4 THEN q.q4
END AS sales
FROM
quarterly_sales AS q
CROSS JOIN
-- ํ์ผ๋ก ์ ๊ฐํ๊ณ ์ถ์ ์ด์ ์๋งํผ ์๋ฒ ํ
์ด๋ธ ๋ง๋ค๊ธฐ
( SELECT 1 AS idx UNION ALL SELECT 2 AS idx UNION ALL SELECT 3 AS idx UNION ALL SELECT 4 AS idx) AS p;
์์์ ๊ธธ์ด๋ฅผ ๊ฐ์ง ๋ฐฐ์ด์ ํ์ผ๋ก ์ ๊ฐํ๊ธฐ
๋ฐ์ดํฐ ๊ธธ์ด๊ฐ ํ์ ๋์ง ์์ ๊ฒฝ์ฐ์๋ ์กฐ๊ธ ๋ณต์ก!
# ํผ๋ฒํ
์ด๋ธ์ ๊ฒฐํฉํ๊ณ , CASE ์์ผ๋ก ๋ ์ด๋ธ ์ด๋ฆ๊ณผ ๋งค์ถ๊ฐ์ ์ถ์ถํด์ ์ด์ ํ์ผ๋ก ๋ณํ!
SELECT
q.year,
-- Q1์์ Q4๊น์ง์ ๋ ์ด๋ธ ์ด๋ฆ ์ถ๋ ฅํ๊ธฐ
CASE
WHEN p.idx = 1 THEN 'q1'
WHEN p.idx = 2 THEN 'q2'
WHEN p.idx = 3 THEN 'q3'
WHEN p.idx = 4 THEN 'q4'
END AS quarter
-- Q1์์ Q4๊น์ง์ ๋งค์ถ ์ถ๋ ฅํ๊ธฐ
, CASE
WHEN p.idx = 1 THEN q.q1
WHEN p.idx = 2 THEN q.q2
WHEN p.idx = 3 THEN q.q3
WHEN p.idx = 4 THEN q.q4
END AS sales
FROM
quarterly_sales AS q
CROSS JOIN
-- ํ์ผ๋ก ์ ๊ฐํ๊ณ ์ถ์ ์ด์ ์๋งํผ ์๋ฒ ํ
์ด๋ธ ๋ง๋ค๊ธฐ
( SELECT 1 AS idx UNION ALL SELECT 2 AS idx UNION ALL SELECT 3 AS idx UNION ALL SELECT 4 AS idx) AS p;
ํ ์ด๋ธ ํจ์๋ฅผ ๊ตฌํํ๊ธฐ! unnest() ํจ์
- ํ ์ด๋ธ ํจ์: ๋ฆฌํด๊ฐ์ด ํ ์ด๋ธ์ธ ํจ์! ๋งค๊ฐ๋ณ์๋ก ๋ฐฐ์ด์ ๋ฐ๊ณ , ๋ฐฐ์ด์ ๋ ์ฝ๋ ๋ถํ ํด์ ๋ฆฌํดํด์ค!
SELECT unnest(ARRAY['A001','A002','A003']) AS product_id;
SELECT purchase_id, product_id
FROM purchase_log AS p CROSS JOIN unnest(string_to_array(product_ids, ',')) AS product_id
-- string_to_array ํจ์๋ก ๋ฌธ์์ด์ ๋ฐฐ์ด๋ก ๋ณํํ๊ณ , unnest ํจ์๋ก ํ
์ด๋ธ๋ก ๋ณํํ๊ธฐ!
- regexp_split_to_table: ๋ฌธ์์ด์ ๊ตฌ๋ถ์๋ก ๋ถํ ํด์ ํ ์ด๋ธํํ๋ ํจ์
SELECT purchase_id, regexp_split_to_table(product_ids, ',') AS product_id
FROM purchase_log;
'SQL' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[SQL] Python๊ณผ PostgreSQL ์ฐ๊ฒฐํ๊ธฐ / psycopg (0) | 2024.07.09 |
---|---|
[๋ฐ์ดํฐ๋ถ์์ ์ํ SQL ๋ ์ํผ] 6๊ฐ : ์ฌ๋ฌ ๊ฐ์ ๊ฐ์ ๋ํ ์กฐ์ (0) | 2023.08.23 |
[Programmers] NULL ์ ๋ฆฌ (0) | 2023.08.16 |
[๋ฐ์ดํฐ๋ถ์์ ์ํ SQL ๋ ์ํผ] 5๊ฐ : ํ๋์ ๊ฐ ์กฐ์ํ๊ธฐ (0) | 2023.08.11 |
[Programmers] Lv4. ์ ์ ์๊ฐ ๊ตฌํ๊ธฐ(2) (0) | 2023.08.11 |
- Total
- Today
- Yesterday
- ์๊ณ ๋ฆฌ์ฆ
- reranker
- NULL์ธ ์ด ๋ง๋ค์ด์ฃผ๊ธฐ
- SELECT๋ฌธ ์ ์๋ธ์ฟผ๋ฆฌ
- ์ฌ๋ฌ๊ฐ ๊ฐ์ ๋ํ ์กฐ์
- SQL๋ ์ํผ
- ํ์ด๋ธ๋ฆฌ๋ ํํฐ๋ง
- ๊ณ ์ ์ ์ถ์ฒ ์๊ณ ๋ฆฌ์ฆ
- ์๋ธ์ฟผ๋ฆฌ
- cold-start
- ORDER BY LIMIT
- ๋ค์ค GROUP BY
- ์ถ์ฒ์์คํ
- ์ด์ฝํ
- groupby ๋ค์ค
- WHERE๋ฌธ ์ง๊ณํจ์
- NULL AS
- ์จ๊ฒจ์ง์กฐ๊ฑด
- rag ๋ค์ค๋ฌธ์ ํ์ฉ
- ํ๋์ ํ ์ด๋ธ์ ๋ํ ์กฐ์
- SET๋ฌธ
- pointwise reranker
- reranker ์๋ ๊ฐ์
- treer๊ตฌ์กฐ
- SQL
- WHERE์ ์๋ธ์ฟผ๋ฆฌ
- llm reranker
- Lagrange Multipler
- SASRec
- ์ฐ๊ด๊ท์น๋ถ์
์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
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 |