엑셀보다 쉬운, SQL

엑셀보다 쉬운, SQL 3주차

Won's log 2023. 4. 27. 17:59

 

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은 실무에서 많이 사용되니

자주 예시를 접하고

시간을 들여서 해결해 보는 것이 중요하다