SQL(2021-06-15)

Hyunjeong Lee·2021년 6월 15일
0

join
二つのテーブルをある項目を基準にして繋げる
エクセルのvlookup機能

inner JOIN
二つのテーブルの交集合

1。二つのテーブルを select * fromで見てみる
2。どの項目で繋げるか決める

left join
片方はデーターが空いている

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

select * from enrolleds e
inner join courses c
on e.course_id = c.course_id;

위 쿼리가 실행되는 순서: from → join → select

  1. from enrolleds: enrolleds 테이블 데이터 전체를 가져옵니다.
  2. inner join courses on e.course_id = c.course_id: courses를 enrolleds 테이블에 붙이는데, enrolleds 테이블의 course_id와 동일한 course_id를 갖는 courses의 테이블을 붙입니다.
  3. select * : 붙여진 모든 데이터를 출력합니다.

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

  • [코드스니펫] 과목별 오늘의 다짐 갯수 세어보기

    select co.title, count(co.title) as checkin_count from checkins ci
    inner join courses co
    on ci.course_id = co.course_id 
    group by co.title

[오늘의 팁!]

2주차에 배운 alias는 이렇게 사용하면 편합니다. 연결되는 테이블이 많아지면서 필드명과 테이블명이 헷갈려 실수할 수 있는데, 이렇게 alias를 지정해 주면 편하고 깔끔하게 SQL 쿼리를 작성할 수 있어요.

  • 배웠던 문법 Join과 함께 연습해보기

    • checkins 테이블에 courses 테이블 연결해서 통계치 내보기

      '오늘의 다짐' 정보에 과목 정보를 연결해 과목별 '오늘의 다짐' 갯수를 세어보자!

      • [코드스니펫] 과목별 오늘의 다짐 갯수 세어보기

        ```sql
        select co.title, count(co.title) as checkin_count from checkins ci
        inner join courses co
        on ci.course_id = co.course_id 
        group by co.title
        ```

        [오늘의 팁!]

        2주차에 배운 alias는 이렇게 사용하면 편합니다. 연결되는 테이블이 많아지면서 필드명과 테이블명이 헷갈려 실수할 수 있는데, 이렇게 alias를 지정해 주면 편하고 깔끔하게 SQL 쿼리를 작성할 수 있어요.

    • point_users 테이블에 users 테이블 연결해서 순서대로 정렬해보기

      유저의 포인트 정보가 담긴 테이블에 유저 정보를 연결해서, 많은 포인트를 얻은 순서대로 유저의 데이터를 뽑아보자!

      • [코드스니펫] 많은 포인트를 얻은 순서대로 유저 데이터 정렬해서 보기

        select * from point_users p
        inner join users u 
        on p.user_id = u.user_id
        order by p.point desc
    • orders 테이블에 users 테이블 연결해서 통계치 내보기

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

      • [코드스니펫] 네이버 이메일 사용하는 유저의 성씨별 주문건수 세어보기

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

    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 테이블 데이터 전체를 가져오고 o라는 별칭을 붙입니다.

    2. inner join users u on o.user_id = u.user_id : users 테이블을 orders 테이블에 붙이는데, orders 테이블의 user_id와 동일한 user_id를 갖는 users 테이블 데이터를 붙입니다. (*users 테이블에 u라는 별칭을 붙입니다)

    3. where u.email like '%naver.com': users 테이블 email 필드값이 naver.com으로 끝나는 값만 가져옵니다.

    4. group by u.name: users 테이블의 name값이 같은 값들을 뭉쳐줍니다.

    5. select u.name, count(u.name) as count_name : users 테이블의 name필드와 name 필드를 기준으로 뭉쳐진 갯수를 세어서 출력해줍니다.

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

    • Left join 언제쓸까요? (복습)

      바로 한번 볼까요?

      예를 들면 모든 유저가 포인트를 갖고 있지를 않을 수 있잖아요!

    • users 테이블과 ↔ point_users 테이블을 left join 해봅시다.

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

      https://s3-us-west-2.amazonaws.com/secure.notion-static.com/f89c8abe-aed0-4a20-82a1-c3a32729706a/Untitled.png

    • 이 상태에선, 이런 게 가능합니다.

      유저 중에, 포인트가 없는 사람(=즉, 시작하지 않은 사람들)의 통계!
      속닥속닥) is NULL , is not NULL 을 함께 배워보아요!

      select name, count(*) from users u
      left join point_users pu on u.user_id = pu.user_id
      where pu.point_user_id is NULL
      group by name
      select name, count(*) 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 name
  • [퀴즈] 여기서 퀴즈! - 막해보기

    7월10일 ~ 7월19일에 가입한 고객 중,
    포인트를 가진 고객의 숫자, 그리고 전체 숫자, 그리고 비율을 보고 싶어요!

    아래와 같은 결과를 보고 싶다면 어떻게 해야할까요?

    • 이렇게 저렇게 해볼까요?

      힌트1 → count 은 NULL을 세지 않는답니다!

      힌트2 → Alias(별칭)도 잘 붙여주세요!

      힌트3 → 비율은 소수점 둘째자리에서 반올림!

      https://s3-us-west-2.amazonaws.com/secure.notion-static.com/f5ec89f2-4724-477b-9b8a-356f18648e0d/Untitled.png

    • 정답 쿼리 살펴보기

      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'

UNION

  • Union을 이용해서 아래와 같은 모습을 만들어볼까요?

    • [코드스니펫] - 퀴즈5 쿼리

      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
    • 보고 싶은 모습!

      https://s3-us-west-2.amazonaws.com/secure.notion-static.com/8a40111d-e2b1-4a6c-bf9f-f0bd1fa91354/Untitled.png

    • 우선, 'month'를 붙여줘야겠네요!

      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 '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
      )
    • 앗, 그런데, 한 가지! 정렬이 깨졌네요!? 😂

      네 맞습니다! union을 사용하면 내부 정렬이 먹지 않아요.

0개의 댓글