๐ Subquery
- ์ฟผ๋ฆฌ ์์ ์ฟผ๋ฆฌ
- ์๋ธ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ง ์์๋ ์ํ๋ ๋ฐ์ดํฐ๋ฅผ ์ถ์ถํ ์ ์์ง๋ง, ๋ ํธํ๊ณ ๊ฐ๋จํ๊ฒ ์ํ๋ ๋ฐ์ดํฐ๋ฅผ ์ถ์ถํด์ค๋ค.
1. ๋น๊ตํ๊ธฐ
inner join VS subquery - ์นด์นด์คํ์ด ๊ฒฐ์ ์ ์ ๋ค์ ์ ๋ณด ๋ณด๊ธฐ
1) inner join
select u.user_id, u.name, u.email from users u
inner join orders o on u.user_id = o.user_id
where o.payment_method = 'kakaopay';
2) Subquery
โ ์นด์นด์คํ์ด๋ก ๊ฒฐ์ ํ user_id ๋ชจ๋ ๊ตฌํ๊ธฐ
select user_id from orders
where payment_method = 'kakaopay'
โก user_id๊ฐ ์๋จ์ ์กฐํ๋ ํ ์ด๋ธ์ ์ํด์๋ ์ ์ ๋ค๋ง ๊ณจ๋ผ๋ณด๊ธฐ
select u.user_id, u.name, u.email from users u
where u.user_id in (
select user_id from orders
where payment_method = 'kakaopay'
)
-> ๊ฒฐ๊ณผ๋ ๊ฐ์!!
-> ์๋ธ์ฟผ๋ฆฌ๋ก ์์ฑ๋ ์ฟผ๋ฆฌ๊ฐ ๋ ์ง๊ด์ ์ผ๋ก ์ ๋ณด์ด๊ณ ๊ฐ๋จํจ.
2. ์์ฃผ ์ฐ์ด๋ ์ ํ
1) Where์ ๋ค์ด๊ฐ๋ ์ ํ
- where ํ๋๋ช in (subquery)
- ์นด์นด์คํ์ด๋ก ๊ฒฐ์ ํ ์ฃผ๋ฌธ ๊ฑด ์ ์ ๋ค๋ง, ์ ์ ํ ์ด๋ธ์์ ์ถ๋ ฅํด์ค
๐โ๏ธ ์คํ ์์
from -> Subquery -> where ..in
(1) from ์คํ: users ๊ฐ์ ธ์ค๊ธฐ
(2) Subquery ์คํ: ํด๋น๋๋ user_id ๋ช ๋จ ๋ฝ์์ค๋ค.
(3) where .. in: subquery ๊ฒฐ๊ณผ์ ํด๋น๋๋ user_id์ ๋ช ๋จ ์กฐ๊ฑด์ผ๋ก ํํฐ๋ง ํด์ค
(4) ๊ฒฐ๊ณผ ์ถ๋ ฅ
select * from users u
where u.user_id in (
select o.user_id from orders o
where o.payment_method = 'kakaopay'
);
- ์ ์ฒด ์ ์ ์ ํฌ์ธํธ ํ๊ท ๋ณด๋ค ํฐ ์ ์ ๋ค์ ๋ฐ์ดํฐ ์ถ์ถํด์ค.
โ ํ๊ท ํฌ์ธํธ ๊ตฌํ๊ธฐ
select avg(pu_avg.point) from point_users pu_avg
โก Subquery์ ๋ฃ๊ธฐ
select * from point_users pu
where pu.point >
(
select avg(pu_avg.point) from point_users pu_avg
);
- '์ด**'์ธ ์ ์ ๋ค์ ํ๊ท ํฌ์ธํธ๋ณด๋ค ๋ ๋ง์ ํฌ์ธํธ ๊ฐ์ง๊ณ ์๋ ๋ฐ์ดํฐ๋ฅผ ์ถ์ถํด์ค.
- ์๋ธ์ฟผ๋ฆฌ ๋ด์์๋ inner join์ด ๊ฐ๋ฅํ๋ค!!
โ '์ด**' ์ ์ ๋ค ํ๊ท ํฌ์ธํธ ๊ตฌํ๊ธฐ
select avg(pu2.point) from point_users pu2
inner join users u on pu2.user_id = u.user_id
where u.name = "์ด**"
โก Subquery์ ์ถ๊ฐํ๊ธฐ
select * from point_users pu
where pu.point >
(
select avg(pu2.point) from point_users pu2
inner join users u
on pu2.user_id = u.user_id
where u.name = "์ด**"
);
2) Select์ ๋ค์ด๊ฐ๋ ์ ํ
- select ํ๋๋ช , ํ๋๋ช , (subquery) from ...
- ์ค๋์ ๋ค์ง ๋ฐ์ดํฐ ๋ณด๊ณ ์ถ์๋ฐ ์ค๋์ ๋ค์ง ์ข์์์ ์๊ฐ ํน์ ์ ์ ๊ฐ(user_id='4b8a10e6') ํ์์ ๋ฐ์๋ ์ข์์ ์์ ๋นํด ์ผ๋ง๋ ๋๊ณ ๋ฎ์์ง ๋น๊ตํด๋ณด๊ธฐ
๐โ๏ธ ์คํ ์์
(1) ์ ์ผ ๋ฐ์ ์๋ select * from ๋ฌธ์์ ๋ฐ์ดํฐ๋ฅผ ํ์ค์ฉ ์ถ๋ ฅํ๋ ๊ณผ์ ์์
(2) select ์์ ์๋ธ์ฟผ๋ฆฌ๊ฐ ๋งค ๋ฐ์ดํฐ ํ์ค๋ง๋ค ์คํ
(3) ํด๋น ๋ฐ์ดํฐ ํ์ค์ user_id ๊ฐ๋ ๋ฐ์ดํฐ์ ํ๊ท ์ข์์์ ๊ฐ์ ์๋ธ์ฟผ๋ฆฌ์์ ๊ณ์ฐ
(4) ๊ฒฐ๊ณผ ์ถ๋ ฅ
โ ํน์ ์ ์ (user_id='4b8a10e6')์ ํ๊ท ์ข์์ ์ ๊ตฌํ๊ธฐ
select avg(likes) from checkins c2
where c2.user_id = '4b8a10e6'
โก Subquery์ ์ถ๊ฐํ๊ธฐ
select c.checkin_id, c.user_id, c.likes,
(
select avg(likes) from checkins c2
where c2.user_id = c.user_id
) as avg_like_user
from checkins c;
- checkins ํ ์ด๋ธ์ checkin_id, course_id, user_id, likes ํ๋์ course_id ํ๊ท like ์ ํ๋์ ๋ณ์นญ ๋ถ์ฌ์ ๋งจ ๋ง์ง๋ง์ ๋ถ์ฌ ์ถ๋ ฅํด๋ณด๊ธฐ
โ checkins ํ ์ด๋ธ์ checkin_id, course_id, user_id, likes ํ๋ ์กฐํํ๊ธฐ
select checkin_id, course_id, user_id, likes,
from checkins c;
โก course_id ํ๊ท like ์ ํ๋ ๊ตฌํ๊ธฐ
select avg(c2.likes) from checkins c2
where c.course_id = c2.course_id
โข ์๋ธ์ฟผ๋ฆฌ์ ๋ณ์นญ(likes_avg) ์ถ๊ฐํด์ ๋งจ ๋ง์ง๋ง ํ๋๋ก ๋ถ์ฌ๋ณด๊ธฐ
select checkin_id, course_id, user_id, likes,
(
select avg(c2.likes) from checkins c2
where c.course_id = c2.course_id
) as likes_avg
from checkins c;
2) From์ ๋ค์ด๊ฐ๋ ์ ํ
- ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ค.
- ๋ด๊ฐ ๋ง๋ select์ ์ด๋ฏธ ์๋ ํ ์ด๋ธ์ joinํ๊ณ ์ถ์ ๋ ์ฌ์ฉ
- ์ ์ ๋ณ ์ข์์ ํ๊ท ๊ตฌํ ํ ์ด๋ธ์์ ํด๋น ์ ์ ๋ณ ํฌ์ธํธ ์ถ๋ ฅํด๋ณด๊ธฐ
โ ์ ์ ๋ณ ์ข์์ ํ๊ท ๊ตฌํ๊ธฐ
select user_id, round(avg(likes),1) as avg_like from checkins
group by user_id
โก ์ ์ ๋ณ ์ข์์ ํ๊ท ๊ตฌํ ํ ์ด๋ธ์ ์๋ธ์ฟผ๋ฆฌ์ ๋ฃ์ด์ ์ ์ ๋ณ ํฌ์ธํธ ๋ณผ ์ ์๊ฒ inner join ํ๊ธฐ
- ํ๊ท ๊ตฌํ ํ ์ด๋ธ์ ๋ณ์นญ ๋ถ์ฌ 'avg_like_table'
select pu.user_id, avg_like_table.avg_like, pu.point from point_users pu
inner join
(
select user_id, round(avg(likes),1) as avg_like from checkins
group by user_id
) avg_like_table on pu.user_id = avg_like_table.user_id
- ์ฝ์ค ์ ๋ชฉ๊ณผ ์ฝ์ค ์ ๋ชฉ๋ณ like ๊ฐ์, ์ฝ์ค๋ณ ์ ์ ์, ์ ์ฒด ์ค like์ ๋น์จ๊น์ง ์ถ๋ ฅํด๋ณด๊ธฐ
โ course_id๋ณ ์ ์ ์ ์ฒดํฌ์ธ ๊ฐ์ ๊ตฌํ๊ธฐ(์ค๋ณต ์ ๊ฑฐํด์ผํจ)
select course_id, count(distinct(user_id)) as cnt_checkins from checkins
group by course_id
โก course_id๋ณ ์ธ์ ๊ตฌํ๊ธฐ
select course_id, count(*) as cnt_total from orders
group by course_id
โข course_id๋ณ like ๊ฐ์์ ์ ์ฒด ์ธ์ ๋ถ์ด๊ธฐ
- โ ๋ณ์นญ 'checkins_cnt_tb' / โก ๋ณ์นญ 'orders_total_tb'
select orders_total_tb.course_id, checkins_cnt_tb.cnt_checkins, orders_total_tb.cnt_total from
(
select course_id, count(*) as cnt_total from orders
group by course_id
) orders_total_tb
inner join
(
select course_id, count(distinct(user_id)) as cnt_checkins from checkins
group by course_id
) checkins_cnt_tb
on orders_total_tb.course_id = checkins_cnt_tb.course_id
โฃ ๋น์จ ๋ํ๋ด๊ธฐ
select orders_total_tb.course_id,
checkins_cnt_tb.cnt_checkins,
orders_total_tb.cnt_total,
(checkins_cnt_tb.cnt_checkins / orders_total_tb.cnt_total) as ratio
from
(
select course_id, count(*) as cnt_total from orders
group by course_id
) orders_total_tb
inner join (
select course_id, count(distinct(user_id)) as cnt_checkins from checkins
group by course_id
) checkins_cnt_tb
on orders_total_tb.course_id = checkins_cnt_tb.course_id
โค ๊ฐ์ ์ ๋ชฉ ๊ฐ์ด ๋ณด์ฌ์ฃผ๊ธฐ
select co.title,
checkins_cnt_tb.cnt_checkins,
orders_total_tb.cnt_total,
(checkins_cnt_tb.cnt_checkins / orders_total_tb.cnt_total) as ratio
from
(
select course_id, count(*) as cnt_total from orders
group by course_id
) orders_total_tb
inner join (
select course_id, count(distinct(user_id)) as cnt_checkins from checkins
group by course_id
) checkins_cnt_tb
on orders_total_tb.course_id = checkins_cnt_tb.course_id
inner join courses co on orders_total_tb.course_id = co.course_id
โจ With
- ์๋ธ์ฟผ๋ฆฌ๋ฅผ ๊น๋ํ๊ฒ ์ ๋ฆฌํด์ค๋ ์ฌ์ฉ
- ์๋ธ์ฟผ๋ฆฌ๋ฅผ ๋ฌถ์ด ๋ณ์นญ์ ๋ถ์ฌํ๊ณ ๋ณ์นญ์ผ๋ก ์๋ธ์ฟผ๋ฆฌ๋ฅผ ์ด์ฉํ ์ ์๋ค.
with table_or as
(
select course_id, count(*) as cnt_total from orders
group by course_id
)
, table_ch as
(
select course_id, count(distinct(user_id)) as cnt_checkins from checkins
group by course_id
)
select co.title,
checkins_cnt_tb.cnt_checkins,
orders_total_tb.cnt_total,
(checkins_cnt_tb.cnt_checkins / orders_total_tb.cnt_total) as ratio
from table_or orders_total_tb inner join table_ch checkins_cnt_tb
on orders_total_tb.course_id = checkins_cnt_tb.course_id
inner join courses co on orders_total_tb.course_id = co.course_id