엑셀보다 쉬운, SQL 3주차
3주 차에는 Join과 Union을 배웠다
Join
테이블과 테이블을 연결한다
이때, 테이블끼리 매칭할 때 '기준' 필요하다
두 테이블의 공통된 정보(key 값)를 기준으로
테이블을 연결해서
한 테이블로 만든다는 것이다
엑셀에서는 vlookup과 비슷하다
실무에서 많이 사용된다
join은
left join과 inner join, outer join으로 나뉜다
*outer join은 잘 사용 안 해서
강의에서 다루지 않았다
left join
A 테이블에다가 B테이블을 붙일 때 사용한다
Null 값은 매칭이 안 됐다는 뜻으로
두 테이블에 모두 가지고 있지 않다는 뜻이다
어디에, 뭐를 붙일 건지, 순서가 중요하다
한쪽에는 있는데 한쪽에는 없는 것을 가지고
통계 내고 싶을 때 사용한다
Null과 관련된 것, 없는 것을 포함할 때 사용한다
*count은 NULL을 세지 않는다!
SELECT * from users u
left join point_users p
on u.user_id = p.user_id
예시)
7월 10일 ~ 7월 19일에 가입한 고객 중,
포인트를 가진 고객의 숫자,
그리고 전체 숫자, 그리고 비율을 구하시오
SELECT count(pu.point_user_id) as pnt_user_cnt,
count(u.user_id) as tot_user,
count(pu.point_user_id)/count(u.user_id)
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'
어려웠던 퀴즈, 복습하고 복습해야징
inner join
쉽게 교집합이다
point가 있는 값(교집합)만 나온다
SELECT * from users u
inner join point_users p
on u.user_id = p.user_id
Left join과 inner join 차이
쉽게 생각하면 Left join은 합집합
Inner join은 교집합이다
중첩된 값을 기준으로 하기에
inner join이 더 잘 활용된다
실습
orders 테이블에 users 테이블 연결해 보기
SELECT * from orders o
inner join users u
on o.user_id = u.user_id
checkins 테이블에 users 테이블 연결해 보기
select * from checkins c
left join users u
on c.created_at = u.created_at
enrolleds 테이블에 courses 테이블 연결해 보기
select * from enrolleds e
inner join courses c
on e.course_id = c.course_id
SQL 쿼리가 실행되는 순서
from -> join -> where -> where -> group by -> select
쿼리 작성하기
결제하고 시작하지 않은 유저들을 성씨별로 세어보기
SELECT u.name, count(*) as cnt from enrolleds e
inner join users u
on e.user_id = u.user_id
where e.is_registered = 0
group by u.name
order by cnt desc
과목 별로 시작하지 않은 유저들을 세어보기
select c.course_id, c.title, count(*) FROM courses c
inner join enrolleds e
on c.course_id = e.course_id
where is_registered = 0
group by c.title
정답
select c.course_id, c.title, count(*) FROM courses c
inner join enrolleds e
on c.course_id = e.course_id
where is_registered = 0
group by c.course_id
결과값은 같으나 group by c.course_id 로 묶은 것의 차이
웹개발, 앱개발 종합반의 week 별 체크인 수를 세어보기
select c.title, c1.WEEK, count(*) as cnt from courses c
inner join checkins c1
on c.course_id = c1.course_id
GROUP by c1.week, c.title
order by c.title , c1.week
위의 값에서, 8월 1일 이후에 구매한 고객들만 발라내어 보기
오답
select * 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 0.created_at like '2020-08%'
정답
select c1.title, c2.week, count(*) 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'
group by c1.title, c2.week
order by c1.title, c2.week
where절, group by 사용이 미숙하다!
Union
두 쿼리를 이어주는 것
단,
union안에서는 order by가 사용되지 않는다.
합친 것에서 order을 해야 한다.
(feat. sub query)
(
select '7월' as month, 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'
group by c1.title, c2.week
order by c1.title, c2.week
)
union all
(
select '8월' as month, 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'
group by c1.title, c2.week
order by c1.title, c2.week
)
숙제
enrolled_id별 수강완료(done=1)한
강의 개수를 세어보고,
완료한 강의 수가 많은 순서대로 정렬해 보기
user_id도 같이 출력되어야 한다
SELECT e.enrolled_id , e.user_id, count(ed.done) as cnt from enrolleds e
inner join enrolleds_detail ed
on ed.enrolled_id = e.enrolled_id
where ed.done = 1
group by e.enrolled_id
order by cnt desc
10분 정도 걸렸다!
[느낀 점]
*쿼리가 점점 복잡해져 간다
그래도 웹개발보다 굉장하게 쉽다
*SQL은 실무에서 많이 사용되니
자주 예시를 접하고
시간을 들여서 해결해 보는 것이 중요하다