Join
- 두 테이블의 공통의 변수(key)를 기준으로 테이블을 연결해서 한 테이블처럼 보는 것
- join은 엑셀의 vlookup과 동일한 기능
- 실행 순서 : from -> join -> select
ex) users 테이블에 point_users 테이블 연결하기
select * from users u
left join point_users p #별칭을 각각 u,p로 설정
on u.user_id = p.user_id #users 테이블의 user_id와 point_user 테이블의 user_id를 같다고 보고 연결해라
join의 종류
1) left join
- 왼쪽에다 붙이는 것

- 한 쪽에는 있는데 한 쪽에는 없는 걸 가지고 통계낼 때 사용
- 포인트가 없는 사람(=시작하지 않은 사람)을 성씨별로 통계내기
select u.name, count(*) from users u
left join point_users pu on u.user_id = pu.user_id
where pu.point_user_id is NULL #NULL은 값이 없다는 의미! 'not NULL'이라고 하면 값이 있는 사람!
group by u.name
- 7월10일 ~ 7월19일에 가입한 고객 중, 포인트를 가진 고객의 숫자, 그리고 전체 숫자, 그리고 비율을 보고 싶어요! ⭐️
select count(pu.point_user_id) as pnt_user_cnt, count(u.user_id) as tot_user_cnt from users u
left join point_users pu on u.user_id = pu.user_id
where u.created_at between '2020-07-10' and '2020-07-20' #부등호 쓰면 안 되고 between으로!
- 줄정렬을 해 주면 훨씬 깔끔하고 보기 좋다!
select count(pu.point_user_id) as pnt_user_cnt,
count(u.user_id) as tot_user_cnt
from users u
left join point_users pu on u.user_id = pu.user_id
where u.created_at between '2020-07-10' and '2020-07-20' #부등호 쓰면 안 되고 between으로!
- 마지막으로 pnt_user_cnt와 tot_user_cnt를 이용해 ratio를 구한다!
select count(pu.point_user_id) as pnt_user_cnt,
count(u.user_id) as tot_user_cnt,
round(count(pu.point_user_id)/count(u.user_id),2) as ratio
from users u
left join point_users pu on u.user_id = pu.user_id
where u.created_at between '2020-07-10' and '2020-07-20'
2) inner join
- 교집합만 남기는 것

- 쿼리는 left join과 동일. left -> inner
- left보다는 inner를 더 많이 사용함. 이걸 기본값으로 사용하기
문법 응용
1) checkins 테이블에 courses 테이블 연결해서 통계치 내보기
- '오늘의 다짐' 정보(checkins)에 과목 정보(courses) 연결해 과목별 '오늘의 다짐' 갯수를 세어보자
- c1의 course_id와 c2의 course_id는 동일값이지만, group by를 하기 위해서는 명확하게 c1인지 c2인지 짚어줘야 한다.
select c1.course_id, count(*) as cnt from checkins c1 #반점을 꼭 적어줘야 함!! -> and의 의미
inner join courses c2 on c1.course_id = c2.course_id
group by c1.course_id
- as ~는 변수의 이름 바꿀 때 사용
- 만약 옆에 변수값을 추가하고 싶으면 select c1.course_id, c2.title, count(*)로 이어주면 됨


2) point_users 테이블에 users 테이블 연결해서 순서대로 정렬해보기
- 유저의 포인트 정보가 담긴 테이블에 유저 정보를 연결해서, 많은 포인트를 얻은 순서대로 유저의 데이터를 뽑아보자!
select * from point_users p
inner join users u on p.user_id = u.user_id
order by p.point desc
- 정렬할 때는 order by 사용. 오름차순이면 그대로 두고 내림차순이면 desc
- user_id, name, email, point만 남기고 싶다면 select를 쓰자
select p.user_id, u.name, u.email, p.point from point_users p
inner join users u on p.user_id = u.user_id
order by p.point desc
3) orders 테이블에 users 테이블 연결해서 통계치 내보기
- 주문 정보에 유저 정보를 연결해 네이버 이메일을 사용하는 유저 중 성씨별 주문건수를 세어보자
- 특정 이메일을 사용하는 유저를 골라내려면 where절을 사용!
select u.name, o.email, count(*) from orders o
inner join users u on o.user_id = u.user_id
where o.email like '%naver.com'
group by u.name
쿼리 연습
1) 결제 수단 별 유저 포인트의 평균값 구해보기
- point_users 에 orders 붙이기
- 포인트가 많은 순으로 정렬하려면 order by 하면 됨!
select o.payment_method, round(avg(pu.point)) from point_users pu
inner join orders o on pu.user_id = o.user_id
group by o.payment_method
order by pu.point desc
- payment_method는 orders에만 있기 때문에(중복 데이터가 아니기 때문에) o.payment_method라고 안 하고 payment_method라고만 입력해도 되긴 됨. 다만, 헷갈릴 수 있으니까 변수를 붙이도록 하자
2) 결제하고 시작하지 않은 유저들을 성씨별로 세어보기
- enrolleds에 users를 붙이기
- 결제수단이 카카오페이인 것만 빼낼 때 [ where payment_method = "kakaopay" ] **where절 형태 까먹지 않기!!
select u.name, count(*) as cnt_name from enrolleds e
inner join users u on e.user_id = u.user_id
where is_registered = 0
group by u.name
order by cnt_name desc
- where 절에서 0은 숫자니까 " " 쓰지 않아도 됨
3) 과목 별로 시작하지 않은 유저들을 세어보기
- courses에 enrolleds 붙이기
select c.course_id, c.title, count(*) as cnt_notstart from courses c
inner join enrolleds e on c.course_id = e.course_id
where e.is_registered = 0
group by c.course_id
4) 웹개발, 앱개발 종합반의 week 별 체크인 수를 세어볼까요? 보기 좋게 정리해보기!
- courses에 checkins을 붙이기
select cr.title, ch.week, count(*) as cnt from checkins ch #checkins와 courses바꿔도 괜찮
inner join courses cr on ch.course_id = cr.course_id
group by ch.week, cr.title
order by cr.title, ch.week #titler과 week의 순서를 바꾸면 week별로 정렬됨


5) 연습4번에서, 8월 1일 이후에 구매한 고객들만 발라내어 보세요!
- courses 테이블에 checkins를 붙이고 checkins에 orders를 한번 더 붙이기
select c1.title, c2.week, count(*) as cnt from courses c1
inner join checkins c2 on c1.course_id = c2.course_id
inner join orders o on c2.user_id = o.user_id
where o.created_at >= '2020-08-01' #8월 1일 이후니까 포함
group by c1.title, c2.week
- inner join을 두 번 써서 세 개의 테이블을 연결할 수 있다.
- where절에서 날짜 조건인 경우 부등호로! [ where o.created_at >= '2020-08-01' ]
union
- 테이블을 합치는 기능
(
select '7월' as month, c.title, c2.week, count(*) as cnt from checkins c2
inner join courses c on c2.course_id = c.course_id
inner join orders o on o.user_id = c2.user_id
where o.created_at < '2020-08-01'
group by c2.course_id, c2.week
order by c2.course_id, c2.week
)
union all
(
select '8월' as month, c.title, c2.week, count(*) as cnt from checkins c2
inner join courses c on c2.course_id = c.course_id
inner join orders o on o.user_id = c2.user_id
where o.created_at > '2020-08-01'
group by c2.course_id, c2.week
order by c2.course_id, c2.week
)
- 괄호 위치와 들여쓰기(tab) 조심하기
- union을 사용하면 내부 정렬이 먹지 않으므로 SubQuery(서브쿼리)를 이용한다.
'SQL' 카테고리의 다른 글
[엑셀보다 쉬운 SQL] 4주차 강의노트 (0) | 2022.07.10 |
---|---|
[엑셀보다 쉬운 SQL] 2주차 강의노트 (0) | 2022.07.02 |
[엑셀보다 쉬운 SQL] 1주차 강의노트 (0) | 2022.06.19 |