[SQL] 기초3

김키키·2022년 9월 8일
0

JOIN

두 테이블의 공통된 정보(key 값)를 기준으로 테이블을 연결해 한 테이블처럼 보는 것.

sql의 join기능은 엑셀의 vlookup과 동일하다.

Left/Inner Join

left join : 왼쪽 테이블(A)을 기준으로 테이블을 합친다.
따라서 어떤 데이터는 모든 필드가 채워져있지만 어떤 필드는 데이터가 비어있다.

SELECT  * from point_users pu 
left join users u 
on pu.user_id = u.user_id 


inner join : 두 테이블의 교집합 데이터만으로 테이블 생성
따라서 비어있는 필드가 있는 데이터가 없다.

select * from users u
inner join point_users pu
on u.user_id = pu.user_id;

=

select * from users u, point_users pu
where u.user_id = pu.user_id;


example

주문 정보에 유저 정보를 연결해 네이버 이메일을 사용하는 유저 중, 성씨별 주문건수를 세어보기

select users.name, count(*) from orders
inner join users 
on orders.user_id = users.user_id 
where users.email like '%naver.com'
group by users.name
select u.name, count(*) from orders o, users u
where o.user_id = u.user_id 
and u.email like '%naver.com'
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,
		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-09' and '2020-07-20'
order by u.created_at 

enrolled_id별 수강완료(done=1)한 강의 갯수를 세어보고, 완료한 강의 수가 많은 순서대로 정렬해보기. user_id도 같이 출력되어야 한다.

select e.enrolled_id, e.user_id, count(*) as cnt from enrolleds e join enrolleds_detail ed 
on e.enrolled_id = ed.enrolled_id 
where ed.done = 1
group by e.enrolled_id, e.user_id
order by cnt desc

group되어야 할 필드 선정부분에서 계속 실수하고 있다.ㅠ

집합연산자

  • Union (합집합) : 중복 행은 한 번만 출력
  • Union All (합집합) : 중복 행 모두 출력
  • Interset (교집합) : 양쪽 select문 결과에 존재하는 데이터만 출력
  • Minus (차집합) : 첫번째 select문에서 두번째 select문의 집합을 뺀 결과 출력

집합연산자는 첫번째 select문과 두번째 select문을 합칠때, 왼쪽부터 순서대로 1:1로 대응하며, 열 개수와 데이터 타입이 일치해야 한다.
열의 순서가 다르거나 데이터 타입이 일치하지 않으면 오류가 발생한다.

#union all
(select '7월' 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월' 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을 사용하면 내부 정렬이 먹지 않는다. 따라서 SubQuery를 사용해야한다.


Join VS Union

하나 이상의 테이블의 데이터를 결합할 때 사용되나 데이터가 결합되는 방식이 다르다.

join

  • Where 조건으로 두개 이상의 테이블에서 원하는 컬럼을 선택해 조회
  • 수평으로 결합한다

union

  • 두개 이상의 select문을 사용해서 그 검색 결과를 합친다
  • 수직으로 결합한다
profile
로그를 남겨보자

0개의 댓글