# ์๋์ฐ ํจ์์ ์ข ๋ฅ

# ์๋์ฐ ํจ์๋ ๋๋์ฒด ์ ์ฌ์ฉํ๋ ๊ฒ์ผ๊น?
A ) ๋ชจ๋ ์ปฌ๋ผ์ ์๊ณ ์ถ์ง ์์ ๋ ์ฌ์ฉํฉ๋๋ค ๐ฅณ
Q ) ์ปฌ๋ผ์ ์๋๋ค๋๊ฒ ๋ฌด์จ์๋ฆฌ์?
์กฐ๊ธ ๋ ์์ธํ ์ค๋ช ํด ์ฃผ์ธ์!!!

์๋ฅผ ๋ค์ด ๋ณด์
CREATE TABLE chat_logs (
user_id VARCHAR(50),
chat_text VARCHAR(255),
review_date DATE
);
โป ์ฐธ๊ณ
dateํ์ผ ๊ฒฝ์ฐ YYYY-MM-DD
timeํ์ผ ๊ฒฝ์ฐ HHH-MI-SS
datetimeํ์ผ ๊ฒฝ์ฐ YYYY-MM-DD HH-MI-SS
ํ์ด ๋๋ค
INSERT INTO chat_logs (user_id, chat_text, review_date) VALUES
('ํผ์นด์ธ', '์๋
์๋
', '2024-01-01'),
('ํผ์นด์ธ', '๋ฐฐ๊ณ ํ', '2024-01-02'),
('ํผ์นด์ธ', '์ฌ์ฌํด', '2024-01-07'),
('ํ์ด๋ฆฌ', '๋ถ๋ญ์ต๊ณ ', '2024-01-01'),
('ํ์ด๋ฆฌ', '์กฑ๋ฐ์ต๊ณ ', '2024-01-02'),
('๊ผฌ๋ถ๊ธฐ', '์ฝ๋ก์ต๊ณ ', '2024-01-01'),
('๊ผฌ๋ถ๊ธฐ', '์งํํ๊ณ ์ถ๋ค!', '2024-01-04');
select *
from chat_logs

์ ํ์์, ์ง๊ณํจ์๋ฅผ ์ฌ์ฉํ์ฌ USER_ID ๋ณ ๊ฐ์ฅ ํฐ ๋ ์ง๋ฅผ ๊ณ์ฐํ๋ฉด, ์๋์ ๊ฐ์ด ๋์ค๊ฒ ์ฃ ?
select user_id,
max(review_date)
from chat_logs
group by user_id

์๋๋ ์ต๋ ๋ ์ง์ ๋ํ text๊ฐ์ '์ฌ์ฌํด' ์ด์ง๋ง

max(review_date)์ ๋ํ chat_text๊ฐ ์ถ๋ ฅ๋์ง๋ ์์ต๋๋ค
select user_id,
chat_text,
max(review_date)
from chat_logs
group by user_id

๋ฐ๋ผ์ ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ 3๊ฐ์ง๊ฐ ์์ต๋๋ค
< 1. ์๋ธ์ฟผ๋ฆฌ ์ฌ์ฉํ๊ธฐ >
- ์๋ ๊ฒฐ๊ณผ๊ฐ์ ์ ๋ต

[ ์ ๋ต 1 ]
select *
from chat_logs
where (user_id, review_date) in
(
select user_id,max(review_date)
from chat_logs
group by user_id
)

< 2. ์ ํ์กฐ์ธ ์ด์ฉ >
โป ์กฐ์ธ์ ์กฐ๊ฑด์ ์ฌ๋ฌ๊ฐ ํ ์ ์๋ค!
select *
from chat_logs c1
inner join (
select user_id,
max(review_date) as max_date
from chat_logs
group by user_id
) as c2
on c1.user_id = c2.user_id
and c1.review_date = c2.max_date

[ ์ ๋ต 2 ]
select c1.user_id,
c1.chat_text,
c1.review_date
from chat_logs c1
inner join (
select user_id,
max(review_date) as max_date
from chat_logs
group by user_id
) as c2
on c1.user_id = c2.user_id
and c1.review_date = c2.max_date

๊ทธ๋ ๋ค๋ฉด ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์์๊น......?!
์๋ค! ์ ๋ต3!!
๋ง์ฝ ์๋์ฐ ํจ์๊ฐ ์๊ฐ๋์ง ์๋๋ค๋ฉด ๋ค์ ์๋ฃ๋ฅผ ์ฐธ์กฐํ์
https://anotherhound.tistory.com/61
[SQL] ์๋์ฐํจ์ ์ด์ ๋ฆฌ
SQL์ ์๋์ฐ ํจ์๋ ํ๊ณผ ํ ๊ฐ์ ๋น๊ต, ์ฐ์ฐ, ์ ์ํ๊ธฐ ์ํ ํจ์์ด๋ค. ๋ถ์ํจ์ ๋๋ ์์ํจ์๋ผ๊ณ ํ๊ธฐ๋ ํ๋ค. ๋ค๋ฅธ ํจ์๋ค์ฒ๋ผ ์ค์ฒฉํด์ ์ฌ์ฉํ ์๋ ์์ง๋ง ์๋ธ์ฟผ๋ฆฌ์์๋ ์ฌ์ฉ๊ฐ๋ฅํ๋ค.
anotherhound.tistory.com
< 3. ์๋์ฐ ํจ์ >
< ์์โ >
- ํ์
์๋์ฐํจ์() over( partition by ์ปฌ๋ผ order by ์ปฌ๋ผ ) as ๋ณ์นญ
1) ๋ค๋ฅธ์์
๋์ผํ๊ฐ - ๋ค๋ฅธ์์
ROW_NUMBER()
ex) 1 2 3 4 1 2
2) ๊ฐ์์์
๋์ผํ๊ฐ - ๊ฐ์์์ / ์ค๊ฐ์์๋ฅผ ๋น์ด๋ค
RANK()
ex) 1 1 3 4 4 6
๋์ผํ๊ฐ - ๊ฐ์์์ / ์ค๊ฐ์์๋ฅผ ๋น์ฐ์ง ์๋๋ค
DENSE_RANK()
ex) 1 1 2 3 3 4
[ ์ ๋ต 3 ]
with ranked_logs as (
select user_id,
chat_text,
review_date,
row_number() over(partition by user_id
order by review_date desc) as review_num
from chat_logs
)
select *
from ranked_logs
where review_num = 1

< โ ์๋์ฐ ํจ์์ ๋ณธ์ง >
group by๋ก ๊ทธ๋ฃนํ ํ ์ฌ์ฉํ ์๋ ์๋ค
๋ณธ๋์ ์๋์ฐ ํจ์์ ์ฑ์ง์ด ์๊ณก๋๊ธฐ ๋๋ฌธ์ด๋ค
์๋์ฐ ํจ์๋ ์๋์ ๋ฐ์ดํฐ์์
select *
from ํ ์ด๋ธ
์์ ์์ ์ปฌ๋ผ์ ์๋ก ์์ฑํ๋ค
๋ฐ๋ผ์ ์ฐ๋ฆฌ๋ where์ ํตํด์ ์์ ์ปฌ๋ผ์ ์กฐ๊ฑด์ ํตํ์ฌ ํํฐ๋ง ํ ์ด์ฉ ๊ฐ๋ฅํ๋ค
select user_id,
chat_text,
review_date,
row_number() over(partition by user_id
order by review_date desc) as review_num
from chat_logs

< ์์โ >
1. FIRST_VALUE
ํํฐ์ ๋ณ ๊ฐ์ฅ ๋จผ์ ๋์จ ๊ฐ์ ๊ตฌํ์ฌ ์ถ๋ ฅํฉ๋๋ค. ๊ณต๋ ๋ฑ์๋ฅผ ์ธ์ ํ์ง ์๊ณ ์ฒ์ ๋์จ ํ๋ง ๊ฐ์ ธ์ค๋ฉฐ MINํจ์๋ฅผ ์ฐ๋ ๊ฒ๊ณผ ๊ฒฐ๊ณผ๊ฐ ๋์ผํฉ๋๋ค.
๋ฌธ๋ฒ: FIRST_VALUE(์ปฌ๋ผ1) OVER(PARTITION BY ์ปฌ๋ผ2 ORDER BY ์ปฌ๋ผ3)
select user_id,
chat_text,
review_date,
first_value(chat_text) over(partition by user_id order by review_date) as first_chat_text
from chat_logs

2. LAST_VALUE
ํํฐ์ ๋ณ ๊ฐ์ฅ ๋ง์ง๋ง์ ๋์จ ๊ฐ์ ๊ตฌํ์ฌ ์ถ๋ ฅํฉ๋๋ค. ๊ณต๋ ๋ฑ์๋ฅผ ์ธ์ ํ์ง ์๊ณ ๋์ค์ ๋์จ ํ๋ง ๊ฐ์ ธ์ค๋ฉฐ MAXํจ์๋ฅผ ์ฐ๋ ๊ฒ๊ณผ ๊ฒฐ๊ณผ๊ฐ ๋์ผํฉ๋๋ค.
๋ฌธ๋ฒ: LAST_VALUE(์ปฌ๋ผ1) OVER(PARTITION BY ์ปฌ๋ผ2 ORDER BY ์ปฌ๋ผ3
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
select user_id,
chat_text,
review_date,
last_value(chat_text) over(partition by user_id order by review_date
rows between unbounded preceding and unbounded following) as last_chat_text
from chat_logs

โป ์ฌ๊ธฐ์ preceding์ด๋?!
PRECEDING ์ด๋ ๊ทธ ์ ์ ๋ผ๋ ๋ป์ ๋๋ค.

3. LAG
์ด์ N ๋ฒ์งธ์ ํ์ ๊ฐ์ ธ์ค๋ ํจ์์ ๋๋ค. N ์ ์ต๋๊ฐ์ผ๋ก 3์ ๊ฐ์ง๋ฉฐ, ๊ธฐ๋ณธ๊ฐ์ 1 ์ ๋๋ค.
๋ฌธ๋ฒ: LAG(์ปฌ๋ผ1) OVER (PARTITION BY ์ปฌ๋ผ2 ORDER BY ์ปฌ๋ผ3)
OR
LAG(์ปฌ๋ผ1, ์ซ์) OVER (PARTITION BY ์ปฌ๋ผ2 ORDER BY ์ปฌ๋ผ3)
โป ์ซ์๋ ์ต๋ 3์ผ๋ก 3๋ฒ์งธ ์ ํ์ ์๋ฏธ
select user_id,
chat_text,
review_date,
lag(chat_text,1) over(partition by user_id order by review_date) as prev_chat_text
from chat_logs

[ ๋ค๋ฅธ ์์ ]
select *
from employees

select *
, LAG(SALARY) OVER (ORDER BY NAME) as PREV_SAL
from employees

4. LEAD
์ดํ Nํ์ ๊ฐ์ ๊ฐ์ ธ์ค๋ ํจ์์
๋๋ค. N ์ ์ต๋๊ฐ์ผ๋ก 3์ ๊ฐ์ง๋ฉฐ, ๊ธฐ๋ณธ๊ฐ์ 1 ์
๋๋ค.
๋ฌธ๋ฒ: LEAD(์ปฌ๋ผ1) OVER (PARTITION BY ์ปฌ๋ผ2 ORDER BY ์ปฌ๋ผ3)
OR
LEAD(์ปฌ๋ผ1, ์ซ์) OVER (PARTITION BY ์ปฌ๋ผ2 ORDER BY ์ปฌ๋ผ3)
โป ์ซ์๋ ์ต๋ 3์ผ๋ก 3๋ฒ์งธ ํ ํ์ ์๋ฏธ
select user_id,
chat_text,
review_date,
lead(chat_text,1) over (partition by user_id order by review_date) as next_chat_text
from chat_logs

< ์ค์ํ ํจ์๋คโ >
1. concat
๋ฌธ์์ด์ ๋ณํฉํ ๋ ์ฌ์ฉํ๋ค
select concat('๊ธธ์ญํ๊ธธ','์ญ์ด')

2. substring
๋ฌธ์์ด์ ์๋ฅผ๋ ์ฌ์ฉํ๋ค
select substring('๋๊ฐ๋จผ๋ฐ๋๊น์ง๊ฒ๋ด๊ฐํ์๋ จ์๋นํ๋ฉฐ๋์๋ฌด๊ฒ๋์๋๋ค',1,4)

3. substring_index
๋ฌธ์์ด์ ํน์ ๊ตฌ๋ถ๊ธฐํธ์ ์ธ๋ฑ์ค ์ ๊น์ง ์ถ๋ ฅํ๋ค
select substring_index('๋ง์๋.์ธ์ด๋ฒ๊ฑฐ,๊ฐ์ํ๊น.๋๋ํ๋ฒ๋จน์ด๋ด!,์ง์ง๊ฟ๋ง.๋ฆฌ์ผ๋ฆฌ.์ฐธํธ๋ฃจ','.',1)

select substring_index('๋ง์๋.์ธ์ด๋ฒ๊ฑฐ,๊ฐ์ํ๊น.๋๋ํ๋ฒ๋จน์ด๋ด!,์ง์ง๊ฟ๋ง.๋ฆฌ์ผ๋ฆฌ.์ฐธํธ๋ฃจ','.',2)

select substring_index('๋ง์๋.์ธ์ด๋ฒ๊ฑฐ,๊ฐ์ํ๊น.๋๋ํ๋ฒ๋จน์ด๋ด!,์ง์ง๊ฟ๋ง.๋ฆฌ์ผ๋ฆฌ.์ฐธํธ๋ฃจ','.',3)

4. ๊ทธ ์ธ ํจ์๋ค


'Knowledge๐ฆข > SQL' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [SQL] Challenge 3ํ์ฐจ ํผ๋๋ถ์ - ๊ฐ์ํ ์ด๋ธ, left ์กฐ์ธ, count(distinct ์ปฌ๋ผ) ๋ฐฑ๋ถ์จ ๊ตฌํ๊ธฐโ๏ธโ๏ธ (0) | 2024.05.30 |
|---|---|
| [SQL] Challenge 2ํ์ฐจ - ์ด๋ํ๊ท ๋ฒ (0) | 2024.05.29 |
| [SQL] ์๋์ฐํจ์ ์ด์ ๋ฆฌ (0) | 2024.05.29 |
| [SQL] NULL ์ฒ๋ฆฌ - ifnull, if์ ์ปฌ๋ผ is null, case๋ฌธ (0) | 2024.05.15 |
| [SQL] group by๋ฅผ ์ฌ์ฉํ๋ ์ด์ - group by, havingโ๏ธ (2) | 2024.05.15 |