본 포스팅은 스파르타코딩클럽 SQL강의를 참고하였습니다.
3주차 강의 목표
😀join까지는 어느정도는 알고있는 내용인데 Union은 처음듣는 용어라 기대되는 강의가 되겠다.
관계가 지어진 여러 테이블에서 원하는 정보들을 엮어서 데이터를 추출할 수 있게 해주는 SQL문법이 Join 이다.
Join은 두 테이블의 공통된 정보 (key값)를 기준으로 테이블을 연결해서 한 테이블처럼 볼 수 있게 해준다.
INNER JOIN(내부 조인)은 두 테이블을 조인할 때, 두 테이블에 모두 지정한 열의 데이터가 있어야 한다.
OUTER JOIN(외부 조인)은 두 테이블을 조인할 때, 1개의 테이블에만 데이터가 있어도 결과가 나온다. LEFT OUTER JOIN, RIGHT OUTER JOIN, FULL OUTER JOIN 모두 외부 조인에 속한다.
CROSS JOIN(상호 조인)은 한쪽 테이블의 모든 행과 다른 쪽 테이블의 모든 행을 조인하는 기능이다.
SELF JOIN(자체 조인)은 자신이 자신과 조인한다는 의미로, 1개의 테이블을 사용한다.
강의 내용에서는 LEFT OUTER JOIN과 INNER JOIN만 잘써도 원하는 대부분의 결과를 얻을 수 있어. 강의 내용에서는 LEFT OUTER JOIN과 INNER JOIN만 강의를 진행한다.
users 테이블과 point_users테이블을 users테이블을 기준으로 left join해보자
select * from users u
left join point_users pu on u.user_id = pu.user_id
SELECT * from 기준이 될 테이블
left join 연결할 테이블 ON 공통된 필드
left join은 기준 테이블의 데이터를 모두 가져오고 연관된 테이블 데이터를 붙이는데, 연관되지 않은 경우는 null필드를 추가해 가져온다.
inner join의 경우는 반드시 두 테이블이 연결지어진 데이터필드만을 가져온다.
select * from users u
inner join point_users pu on u.user_id = pu.user_id
*
) from checkins ch7-04 추가
7월 데이터와 8월 데이터를 보려면 각각
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
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
두 번의 쿼리 실행으로 따로따로 봐야하는데 이러한 두번의 과정을 한번에 처리할 수 있는 것이 union이다.
(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)
두 개의 쿼리를 각각 ()
로 하나의 묶음으로 묶고 중앙에 union all
을 통해서 한번에 처리할 수 있도록 동작시킨다.
하지만 union을 사용하면 위의 그림과 같이 쿼리에서는 order by를 이용해 정렬을 해주었지만, 위 그림에서 정렬이 흐트러진것을 볼 수 있다. 일반적으로 union만 사용하게 되면 내부 정렬이 적용되지 않는다. 이러한 문제점을 해결할 수 있는 방법으로 subQuery(서브쿼리)가 존재하는데 다음포스팅에서 정리해 보자.
숙제 문제
enrolled_id별 수강완료(done=1)한 강의 갯수를 세어보고, 완료한 강의 수가 많은 순서대로 정렬해보기. user_id도 같이 출력되어야 한다.
select e.enrolled_id,
e.user_id,
count(*
)
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 count desc