INNER JOIN
LEFT JOIN
종류가 더 있지만 배운건 위 두 가지
A테이블과 B테이블의 공통된 부분을 출력
ex) 같은 성씨를 가진 네이버 이메일로 주문한 사람들의 수
SELECT u.name, COUNT(*) as cnt FROM orders o
INNER JOIN users u
ON o.user_id = u.user_id
WHERE o.email LIKE '%naver.com'
GROUP BY u.name;
쿼리가 실행되는 순서: from → join → where → group by → select
ex) 각 반의 8월 1일 이후 week별 체크인 수 통계
SELECT co.title, ch.week, COUNT(*) as cnt FROM checkins ch
INNER JOIN courses co
ON ch.course_id = co.course_id
INNER JOIN orders o
ON ch.user_id = o.user_id
WHERE o.created_at >= '2020-08-01'
GROUP BY co.title, ch.week
ORDER BY co.title, ch.week
그냥 조인을 두번 쓰면 된다.
INNER JOIN과 달리 기준이 되는 테이블을 잘 정해야함
A테이블과 B테이블을 비교해서 A가 가진 값이 B에도 있는 경우를 포함하여 출력하고 A가 가진 값이 B에 없는 경우는 NULL로 표시한다
ex) 가입은 되어있어서 B에 user id가 있긴하지만 강의를 시작한 이력이 없어서 point가 없는 경우
SELECT u.user_id, pu.point_user_id from users u
left join point_users pu on u.user_id = pu.user_id;
ex) 가입은 했지만 강의 시작은 안한사람 성씨별로
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 NULL
GROUP BY u.name
ORDER BY COUNT(*) DESC;
IS NULL 로 시작 안한사람 구할 수 있고
IS NOT NULL 로 시작한 사람을 구할 수 있다.
ex) 특정 기간 가입 고객중 시작 유무별 고객수와 비율
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-10' and '2020-07-20'
COUNT는 NULL은 자동으로 안센다
두 쿼리결과를 합치는 명령어
ex)
(
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
)
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
)
union은 내부 쿼리의 order가 먹히지 않는다.
정렬을 하려면 서브쿼리라는 개념을 이용해야한다.