join
二つのテーブルをある項目を基準にして繋げる
エクセルのvlookup機能
inner JOIN
二つのテーブルの交集合
1。二つのテーブルを select * fromで見てみる
2。どの項目で繋げるか決める
left join
片方はデーターが空いている
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
select * from enrolleds e
inner join courses c
on e.course_id = c.course_id;
위 쿼리가 실행되는 순서: from → join → select
항상 from에 들어간 테이블을 기준으로, 다른 테이블이 붙는다고 생각하면 편합니다!
[코드스니펫] 과목별 오늘의 다짐 갯수 세어보기
select co.title, count(co.title) as checkin_count from checkins ci
inner join courses co
on ci.course_id = co.course_id
group by co.title
[오늘의 팁!]
2주차에 배운 alias는 이렇게 사용하면 편합니다. 연결되는 테이블이 많아지면서 필드명과 테이블명이 헷갈려 실수할 수 있는데, 이렇게 alias를 지정해 주면 편하고 깔끔하게 SQL 쿼리를 작성할 수 있어요.
배웠던 문법 Join과 함께 연습해보기
checkins 테이블에 courses 테이블 연결해서 통계치 내보기
'오늘의 다짐' 정보에 과목 정보를 연결해 과목별 '오늘의 다짐' 갯수를 세어보자!
[코드스니펫] 과목별 오늘의 다짐 갯수 세어보기
```sql
select co.title, count(co.title) as checkin_count from checkins ci
inner join courses co
on ci.course_id = co.course_id
group by co.title
```
[오늘의 팁!]
2주차에 배운 alias는 이렇게 사용하면 편합니다. 연결되는 테이블이 많아지면서 필드명과 테이블명이 헷갈려 실수할 수 있는데, 이렇게 alias를 지정해 주면 편하고 깔끔하게 SQL 쿼리를 작성할 수 있어요.
point_users 테이블에 users 테이블 연결해서 순서대로 정렬해보기
유저의 포인트 정보가 담긴 테이블에 유저 정보를 연결해서, 많은 포인트를 얻은 순서대로 유저의 데이터를 뽑아보자!
[코드스니펫] 많은 포인트를 얻은 순서대로 유저 데이터 정렬해서 보기
select * from point_users p
inner join users u
on p.user_id = u.user_id
order by p.point desc
orders 테이블에 users 테이블 연결해서 통계치 내보기
주문 정보에 유저 정보를 연결해 네이버 이메일을 사용하는 유저 중, 성씨별 주문건수를 세어보자!
[코드스니펫] 네이버 이메일 사용하는 유저의 성씨별 주문건수 세어보기
select u.name, count(u.name) as count_name from orders o
inner join users u
on o.user_id = u.user_id
where u.email like '%naver.com'
group by u.name
SQL 쿼리가 실행되는 순서
select u.name, count(u.name) as count_name from orders o
inner join users u
on o.user_id = u.user_id
where u.email like '%naver.com'
group by u.name
위 쿼리가 실행되는 순서: from → join → where → group by → select
from orders o: orders 테이블 데이터 전체를 가져오고 o라는 별칭을 붙입니다.
inner join users u on o.user_id = u.user_id : users 테이블을 orders 테이블에 붙이는데, orders 테이블의 user_id와 동일한 user_id를 갖는 users 테이블 데이터를 붙입니다. (*users 테이블에 u라는 별칭을 붙입니다)
where u.email like '%naver.com': users 테이블 email 필드값이 naver.com으로 끝나는 값만 가져옵니다.
group by u.name: users 테이블의 name값이 같은 값들을 뭉쳐줍니다.
select u.name, count(u.name) as count_name : users 테이블의 name필드와 name 필드를 기준으로 뭉쳐진 갯수를 세어서 출력해줍니다.
Join의 실행 순서는 항상 from 과 붙어다닌다고 생각하면 편해요!
Left join 언제쓸까요? (복습)
바로 한번 볼까요?
예를 들면 모든 유저가 포인트를 갖고 있지를 않을 수 있잖아요!
users 테이블과 ↔ point_users 테이블을 left join 해봅시다.
select * from users u
left join point_users pu on u.user_id = pu.user_id
이 상태에선, 이런 게 가능합니다.
유저 중에, 포인트가 없는 사람(=즉, 시작하지 않은 사람들)의 통계!
속닥속닥) is NULL
, is not NULL
을 함께 배워보아요!
select name, count(*) from users u
left join point_users pu on u.user_id = pu.user_id
where pu.point_user_id is NULL
group by name
select name, count(*) from users u
left join point_users pu on u.user_id = pu.user_id
where pu.point_user_id is not NULL
group by name
[퀴즈] 여기서 퀴즈! - 막해보기
7월10일 ~ 7월19일에 가입한 고객 중,
포인트를 가진 고객의 숫자, 그리고 전체 숫자, 그리고 비율을 보고 싶어요!
아래와 같은 결과를 보고 싶다면 어떻게 해야할까요?
이렇게 저렇게 해볼까요?
힌트1 → count
은 NULL을 세지 않는답니다!
힌트2 → Alias(별칭)도 잘 붙여주세요!
힌트3 → 비율은 소수점 둘째자리에서 반올림!
정답 쿼리 살펴보기
select count(point_user_id) as pnt_user_cnt,
count(*) as tot_user_cnt,
round(count(point_user_id)/count(*),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'
UNION
Union을 이용해서 아래와 같은 모습을 만들어볼까요?
[코드스니펫] - 퀴즈5 쿼리
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'
group by c1.title, c2.week
order by c1.title, c2.week
보고 싶은 모습!
우선, 'month'를 붙여줘야겠네요!
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 '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
)
앗, 그런데, 한 가지! 정렬이 깨졌네요!? 😂
네 맞습니다! union을 사용하면 내부 정렬이 먹지 않아요.