SQL join과 union

Stian·2023년 6월 30일

SQL에서 join과 union 배우기

join문 : 테이블과 테이블을 붙이는 것. 모든 쿼리에 조인이 들어간다고 봐도 무방함. 예를 들어, 오늘의 다짐 이벤트 당첨자를 선정해서 기프티콘을 준다. 10명 추첨해서 깊티 지급~ 그리고 join을 사용해서 key값으로 두 테이블을 연결하곤함. 엑셀의 vlookup과 동일함

종류 : left join(합집합(=), inner join

A테이블을 기준으로 B를 붙인다거나한다. 
  • 예제1

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

select c1.course_id, count(*) as cnt from checkins c1
inner join courses c2 on c1.course_id = c2.course_id #이줄에서 한번에 정의함.;
group by c1.course_id #c1과 c2중에 하나로 , course id별 개수를 정의하되 개수 변수 명칭은 cnt.

  • 예제 2

select c1.course_id, c2.title, count(*) as cnt from checkins c1
inner join courses c2 on c1.course_id = c2.course_id #이줄에서 한번에 정의함.;
group by c1.course_id #c1과 c2중에 하나로 , course id별 개수를 정의하되 개수 변수 명칭은 cnt. 그려면 변수 두개가 뜬다.

  • 많은 포인트를 얻은 순서대로 유저 데이터를 정렬해서 보기.

    select * from point_users pu
    inner join users u on pu.user_id = u.user_id
    order by pu.point desc #point 열은 원래 users 테이블에서 비롯된 것이기 때문에... pu.를 써주어야 함.

  • orders 테이블에 users 연결하기. 네이버 메일 사용하는 유저의 성씨별 주문건수 세어보기. 뒤에 끼워젛는 것을 inner join 바로 다음에 쓰는 것이다.

    select u.name, count(*) from orders o
    inner join users u on o.user_id = u.user_id
    where o.email like '%naver.com'
    group by u.name

    select from orders o
    select
    from point_users pu
    inner join orders o on pu.user_id = o.user_id

  • 두번째 퀴즈 : 결제했는데 아직 시작 안한사람..

    select u.name, count(*) as cnt_name 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_name desc

  • 세번째 퀴즈 : week별 체크인 수를 세어보기

    select c.title, ch.week,count(*) as cnt from courses c
    inner join checkins ch on c.course_id = ch.course_id
    group by c.title, ch.week
    order by c.title

  • inner join 두 번 해서 테이블 세개묶기.

    select * from courses c
    inner join checkins ch on c.course_id = ch.course_id
    inner join orders o on ch.user_id = o.user_id #어차피 직전에 checkin붙인 것이 효력이 생겨버려서, 한꺼번에 실행되는 것을 염두에 두면 이렇게 inner join 두 번 써도 무방하다.
    where o.created_at >='2020-08-01'

  • left join은 언제 쓰이는 걸까? 이것은 합집합

    select u.name, count(*) as cnt 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 u.name

*7월 10-19일 가입한 고객 중 포인트를 가진 고객의 숫자, 전체 숫자, 비율을 보고싶다.

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

select count(pu.point_user_id) as pnt_user_cnt,
count(u.user_id) as tnt_user_cnt,
round(count(pu.point_user_id)/count(u.user_id),2)
from users u #u를 기준으로 해야, NULL아닌것들이 세진다. 근데 이게 옆의 수랑 소급하는것이 아닌가봄 ㅇㅇ
left join point_users pu on u.user_id = pu.user_id
where u.created_at between '2020-07-10' and '2020-07-20' #알아서 NULL 제끼고 count되는 것이 디폴트다

#Union : select를 두 번하는 것이 아니라 한번에 붙여ㅑ주기..

(
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 #8월달의 쿼리 '8월 as month' 라고 맨 처음에 정의하는 것임. 맨 처음에 변수명과 함께 정의하기.
)
#union all에서는 order by가 먹히질 않는다는 특징이 있음.

* homework(어렵..) 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

0개의 댓글