SQL - Join, Union

murphytklee·2023년 4월 21일
0
post-thumbnail

[목표]

  1. 여러 테이블의 정보를 연결하는 Join을 이해한다.
  2. 연결된 정보를 바탕으로 보다 풍부한 데이터분석을 연습한다.
  3. 아래 위로 결과를 연결하는 Union을 공부한다.

1. Join 여러 테이블을 연결할 때

📌 Join이란?

  • 두 테이블의 공통된 정보 (key값)를 기준으로 테이블을 연결해서 한 테이블처럼 보는 것을 의미한다.
  • SQL의 Join은 엑셀의 vlookup과 동일하다고 생각하면 된다.
  • Inner Join 개념
    select * from users u
    inner join point_users p on u.user_id = p.user_id;
    • 같은 user_id를 두 테이블에서 모두 가지고 있는 데이터만 출력했기 때문에 여기서는 비어있는 필드가 있는 데이터가 없다.


  • Left Join 개념
    select * from users u
    left join point_users p on u.user_id = p.user_id;
    • left join은 어디에 → 뭐를 붙일건지, 순서가 중요 하다.

  • 어떤 데이터는 모든 필드가 채워져있지만, 어떤 데이터는 비어있는 필드가 있다.
  • 꽉찬 데이터: 해당 데이터의 user_id 필드값이 point_users 테이블에 존재해서 연결한 경우
  • 비어있는 데이터: 해당 데이터의 user_id 필드값이 point_users 테이블에 존재하지 않는 경우


  • SQL 쿼리가 실행되는 순서
    select * from enrolleds e
    inner join courses c
    on e.course_id = c.course_id
📌 쿼리가 실행되는 순서: from → join → select

1. from enrolleds e
2. inner join courses on e.course_id = c.course_id
3. select *

💡 항상 from에 들어간 테이블을 기준으로, 다른 테이블이 붙는다고 생각하면 편하다.

  • SQL 쿼리가 실행되는 순서 2
    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

1. from orders o: orders
2. inner join users u on o.user_id = u.user_id
3. where u.email like '%naver.com'
4. group by u.name
5. select u.name, count(u.name) as count_name

💡 Join의 실행 순서는 항상 from 과 붙어다닌다고 생각하면 편하다.

2. Inner Join 연습

  • Inner Join, where, group by, order by 같이 사용하기

❓ 결제하고 시작하지 않은 유저들을 성씨별로 세어보기

  select 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 name
  order by cnt_name desc
  • Inner Join 두번 걸고 group by콤마로 이어 걸기

❓ 웹개발, 앱개발 종합반의 week 별 체크인 수를 세어 8월 1일 이후에 구매한 고객들만 발라내기

   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

3. Left Join 연습

  • count는 null 을 세지 않는다

    ❓ 7월10일 ~ 7월19일에 가입한 고객 중,포인트를 가진 고객의 숫자, 그리고 전체 숫자, 그리고 비율 구하기

    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'


4. Union 결과물 합치기

  • union을 사용하면 내부 정렬(order by)가 적용되지 않는다.

    (
    	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
    )


5. 과제

✏️ enrolled_id별 수강완료(done=1)한 강의 갯수를 세어보고, 완료한 강의 수가 많은 순서대로 정렬해보기. user_id도 같이 출력되어야 한다.
select e.enrolled_id,
	     e.user_id,
	     count(*) as cnt
  from enrolleds e
 inner 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

profile
murphytklee.tistory.com 이사갑니다. 옮겨지는 게시글은 비공개 처리합니다.

0개의 댓글

관련 채용 정보