( ) 괄호 안의 명령어부터 실행
이후에 밖에 있는 명령어를 실행
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'
Subquery를 사용할 경우
# 원본
select user_id from orders
where payment_method = 'kakaopay'
# 수정본
select u.user_id, u.name, u.email from users u
where u.user_id in ( # ( ) 괄호에 속하는 u.user_id만 가져오기
select o.user_id from orders o
where o.payment_method = 'kakaopay'
)
where 필드명 in (subquery)
select * from point_users pu
where pu.point > ( # 평균보다 큰 유저들
select avg(pu2.point) from point_users pu2 # 전체 유저의 포인트의 평균
)
where 필드명 > (subquery)
형태로도 사용 가능하다.# 방법 1
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 * from point_users pu
where pu.point > (
select avg(pu2.point) from point_users pu2
where user_id in (
select user_id from users
where name = '이**'
)
)
point_users 테이블과 users 테이블의 교집합을 구하는데, '이**' 조건으로 user_id 값을 맞춰서 구한다.
select (select ... (select ...)) 이렇게 select 안에 계속 select 를 이어나갈 수도 있다.
# 원본
select avg(likes) from checkins c2
where c2.user_id = '4b8a10e6'
# 수정본
select c.checkin_id,
c.user_id,
c.likes,
(
select avg(likes) from checkins
where user_id = c.user_id
) as avg_like_user
from checkins c # c 테이블
select 필드명, 필드명, (subquery) from ...
select 쿼리문이 한줄씩 실행될 때마다, () 괄호 안의 명령어가 실행된다.
select * from point_users pu
where pu.point > (
select avg(pu2.point) from point_users pu2
where user_id in (
select user_id from users
where name = '이**'
)
)
select c.checkin_id,
c.course_id,
c.user_id,
c.likes,
(
select avg(likes) from checkins # 평균 likes수
where course_id = c.course_id # course_id별
) as course_avg
from checkins c # checkins 테이블에
select c.checkin_id,
c2.title, # 과목명별
c.user_id,
c.likes,
(
select round(avg(likes),1) from checkins # 평균 likes수
where course_id = c.course_id
) as course_avg
from checkins c # checkins 테이블에
inner join courses c2 on c.course_id = c2.course_id # 과목명별
가장 많이 사용되는 유형
내가 만든 Select와 이미 있는 테이블을 Join하고 싶을 때 사용
내가 만든 select 문을 마치 원래 존재했던 테이블처럼 사용하는 방식
# 원본
select user_id, round(avg(likes),1) as avg_like from checkins
group by user_id
# 수정본
select pu.user_id, a.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
) a on pu.user_id = a.user_id
a
: () 괄호의 테이블 이름(즉, 괄호를 지칭함)# 준비 1 : course_id별 유저의 체크인 개수
select course_id, count(distinct(user_id)) as cnt_checkins from checkins
group by course_id
# 준비 2 : course_id별 인원 수
select course_id, count(*) as cnt_total from orders
group by course_id
# from : 준비 1 + 준비 2
select a.course_id,
b.cnt_checkins,
a.cnt_total
from
(
select course_id, count(*) as cnt_total from orders # 준비 2
group by course_id
) a
inner join (
select course_id, count(distinct(user_id)) as cnt_checkins from checkins # 준비 1
group by course_id
) b
on a.course_id = b.course_id # a.course_id 와 b.course_id 가 같은 것으로 join한다
# from(준비 1 + 준비 2) + 퍼센트
select a.course_id,
b.cnt_checkins,
a.cnt_total,
(b.cnt_checkins/a.cnt_total) as ratio # 퍼센트
from
(
select course_id, count(*) as cnt_total from orders
group by course_id
) a
inner join (
select course_id, count(distinct(user_id)) as cnt_checkins from checkins
group by course_id
) b
on a.course_id = b.course_id
# from(준비 1 + 준비 2) + 퍼센트 + 강의 제목
select c.title, # 강의 제목
a.cnt_checkins,
b.cnt_total,
(a.cnt_checkins/b.cnt_total) as ratio
from
(
select course_id, count(distinct(user_id)) as cnt_checkins from checkins
group by course_id
) a
inner join
(
select course_id, count(*) as cnt_total from orders
group by course_id
) b
on a.course_id = b.course_id
inner join courses c on a.course_id = c.course_id # 강의 제목
from : 준비 1 + 준비 2
from(준비 1 + 준비 2) + 퍼센트 + 강의 제목
서브쿼리가 붙어서 inner join 안쪽이 헷갈릴 때 사용하는 것이 with절
with 절을 실행할 때는 전체 명령어를 마우스로 블록 씌워서 실행해야 한다. (그렇지 않으면 일부만 실행됨)
# 원본
select c.title,
a.cnt_checkins,
b.cnt_total,
(a.cnt_checkins/b.cnt_total) as ratio
from
(
select course_id, count(distinct(user_id)) as cnt_checkins from checkins
group by course_id
) a
inner join
(
select course_id, count(*) as cnt_total from orders
group by course_id
) b on a.course_id = b.course_id
inner join courses c on a.course_id = c.course_id
# 수정본
with table1 as (
select course_id, count(distinct(user_id)) as cnt_checkins from checkins
group by course_id
), table2 as (
select course_id, count(*) as cnt_total from orders
group by course_id
)
select c.title,
a.cnt_checkins,
b.cnt_total,
(a.cnt_checkins/b.cnt_total) as ratio
from table1 a inner join table2 b on a.course_id = b.course_id
inner join courses c on a.course_id = c.course_id
with 테이블명1 as (...), 테이블명2 as (...) select ...
# 준비 1
select enrolled_id, count(*) as cnt_done from enrolleds_detail ed
where done = 1
group by enrolled_id
# 준비 2
select enrolled_id, count(*) as cnt_total from enrolleds_detail ed
group by enrolled_id
# Subquery(준비 1 + 준비 2)
select a.enrolled_id, a.done_cnt, b.total_cnt from (
select enrolled_id, count(*) as cnt_done from enrolleds_detail ed
where done = 1
group by enrolled_id
) a
inner join (
select enrolled_id, count(*) as cnt_total from enrolleds_detail ed
group by enrolled_id
) b on a.enrolled_id = b.enrolled_id
# Subquery(준비 1 + 준비 2) + with
with table1 as (
select enrolled_id, count(*) as cnt_done from enrolleds_detail ed
where done = 1
group by enrolled_id
) table2 as (
select enrolled_id, count(*) as cnt_total from enrolleds_detail ed
group by enrolled_id
)
select a.enrolled_id,
a.cnt_done,
b.cnt_total
from table1 a
inner join table2 b on a.enrolled_id = b.enrolled_id
with table1 as (
select enrolled_id, count(*) as cnt_done from enrolleds_detail ed
where done = 1
group by enrolled_id
) table2 as (
select enrolled_id, count(*) as cnt_total from enrolleds_detail ed
group by enrolled_id
)
select a.enrolled_id,
a.cnt_done,
b.cnt_total
round(a.done_cnt/b.total_cnt,2) as ratio
from table1 a
inner join table2 b on a.enrolled_id = b.enrolled_id
# 그러나, 더 간단히 만들면
select enrolled_id,
sum(done) as cnt_done, # 어차피 done은 1 또는 0 이기 때문
count(*) as cnt_total,
round(sum(done)/count(*),2) as ratio
from enrolleds_detail
group by enrolled_id