SQL

SQL 3주차 단어/문법 정리

Sehe_e 2023. 2. 27. 00:08

 

 

 

Key

: 데이터의 연결이 필요한 두 테이블에 공통으로 존재하며 연결해주는 역할을 할 수 있는 필드

 

+) 한 테이블에 모든 정보를 담을 수도 있겠지만, 불필요하게 테이블의 크기가 커지기 때문에,

    데이터를 종류별로 쪼개 다른 테이블에 담아놓고 연결이 필요한 경우 활용이 가능하도록 만들어놓는다.

 

 

Join

: 두 테이블의 Key값을 기준으로 테이블을 연결해서 한 테이블처럼 보는 것을 의미한다.

 

+) 엑셀에서의 VLOOKUP과 같다.

 

 

 


- Join 문법 정리 -

 

 

 

Inner join / on ~

: A 테이블에 B 테이블을 Inner join할 경우, 조회 테이블에 NULL 데이터가 없다.

 

= Key 필드로 연결 후, A 테이블의 필드 데이터와 B 테이블의 필드 데이터를

   inner join하여 조회 테이블에서 공백이 없는 데이터만 보여준다.

 

 

Inner join, A와 B의 교집합이다.

 

select * from 테이블명 Alias
inner join 테이블명2 Alias2
on Alias.Key필드명 = Alias2.Key필드명

+) from 뒤엔 연결의 기준이 되는 테이블A를,

     inner join 뒤엔 붙이고 싶은 테이블B를 적는다.

     그 후 ' on A.Key필드 = B.Key필드 ' 로 이어주면 된다.

 

 

 

 - enrolleds 테이블에 courses 테이블을 inner join 해보기 -

 

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

 > 쿼리 실행 순서

 

1) enrolleds 테이블 데이터를 가져온다.

   ( from enrolleds e )

 

2) courses 테이블을 가져와서 course_id라는 동일한 필드(Key)를 기준으로 enrolleds 테이블에 붙인다.

   ( inner join courses c

     on e.course_id = c.course_id )

 

3) 모든 데이터를 조회한다.

   ( select * )

 

 

> 결과값

 

 


 

 

Left join / on ~

: A 테이블에 B 테이블을 Left join할 경우, 비어있는 데이터(NULL)가 생길 수 있다.

 

= Key 필드로 연결 후, A 테이블의 필드에 맞는 B 테이블의 필드 데이터의 유무에 따라

   Left Join 후 조회 테이블의 데이터의 유무 차이가 생긴다.

 

Left join, A에 맞춰 B를 더한다.

 

select * from 테이블명 Alias
left join 테이블명2 Alias2
on Alias.Key필드명 = Alias2.Key필드명

+) Left join은 from 테이블과 join 테이블의 위치가 중요하다.

    from 테이블을 기준으로 join 테이블의 데이터를 붙이기 때문이다.

 

+) Count는 Null을 세지 않는다.

 

 

 - users 테이블에 point_users 테이블을 left join하기 -

 

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

 

> 결과값

 


 

Left join

- is Null

: where절로 Null이 존재하는 필드에서 사용시 Null인 데이터만 조회된다.

 

select * from 테이블명 Alias
left join 테이블명2 Alias2
on Alias.Key필드명 = Alias2.Key필드명
where Alias.(Null이 존재하는 필드) is 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

 

> 결과값

 


 

Left join

is not Null

: where절로 Null이 존재하는 필드에서 사용시 Null이 아닌 데이터만 조회된다.

 

select * from 테이블명 Alias
left join 테이블명2 Alias2
on Alias.Key필드명 = Alias2.Key필드명
where Alias.(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 not NULL
group by name

 

> 결과값

 

 


- 이 외 유용한 문법 -

 

 

Round

: 소수를 반올림하여 출력해주는 명령어, Round(숫자,자릿수)로 적는다.

 

select round((필드명),출력할 소수점 자리의 갯수) from 테이블명
group by 필드명

 

 

 - 결제수단별 유저 포인트의 평균값 구해보기 -

 

select o.payment_method, round(AVG(p.point)) from point_users p
inner join orders o 
on p.user_id = o.user_id 
group by o.payment_method

- Avg

: 평균을 출력해준다.

 

 


 

Union  // all

: Select 두 번의 결과를 한 번에 모아서 출력해준다.

 

+) Union으로 합칠 두 개의 Select 출력 필드명이 같아야한다.

 

 

 

 - 8월에 웹개발 앱개발반을 수강시작한 유저의 수와 결제수단을 출력하기 -

 

SELECT '8월' as month,
	   o.course_title,
	   o.payment_method,
	   count(o.created_at) as start_user
  from orders o
inner join users u
on o.user_id = u.user_id 
where o.created_at >= '2020-08-01'
group by payment_method

 

 

 

 - 7월에 웹개발 앱개발반을 수강시작한 유저의 수와 결제수단을 출력하기 -

 

SELECT '8월' as month,
	   o.course_title,
	   o.payment_method,
	   count(o.created_at) as start_user
  from orders o
inner join users u
on o.user_id = u.user_id 
where o.created_at >= '2020-08-01'
group by payment_method

 

 

 

 - 7월과 8월, 각각 웹개발 앱개발반을 수강시작한 유저의 수와 결제수단을 한 번에 출력하기 -

 

(
SELECT '7월' as month,
	   o.course_title,
	   o.payment_method,
	   count(u.user_id) as start_user
  from orders o
inner join users u
on o.user_id = u.user_id 
where o.created_at < '2020-08-01'
group by payment_method
)
union all
(
SELECT '8월' as month,
	   o.course_title,
	   o.payment_method,
	   count(o.created_at) as start_user
  from orders o
inner join users u
on o.user_id = u.user_id 
where o.created_at >= '2020-08-01'
group by payment_method
)

 

+) Union을 사용하면 내부정렬(order by)이 적용되지 않는다.

    그렇기 때문에 SubQuery(4주차)를 사용해야 한다.

 

 

 


- 복습하기 -

 

 

 

 [ inner join ]

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

 

SELECT c2.title, count(*) as cnt from checkins c
inner join courses c2
on c.course_id = c2.course_id
group by c2.title

 

 

 

 [ inner join, order by ]

 - 많은 포인트를 얻은 순서대로 유저의 데이터를 뽑아보기 -

 

SELECT u.user_id, point from point_users pu
inner join users u
on pu.user_id = u.user_id
order by pu.point desc

 

 

 

 [ inner join, like, group by, count ]

 - 네이버 이메일을 사용하는 유저 중, 성씨별 주문건수를 세어보기 -

 

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

 

 

 

 [ inner join, =, group by, order by, count ]

 - 결제하고 시작하지 않은 유저들을 성씨별, 많은 순으로 세어보기 -

 

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

 

 

 

 [ inner join, =, group by, count ]

 - 과목 별로 시작하지 않은 유저들을 세어보기 -

 

SELECT c.title, count(*) from courses c
inner join enrolleds e
on c.course_id = e.course_id
where e.is_registered = 0
group by c.title

 

 

 

 [ inner join, group by, order by, count ]

 - 웹개발, 앱개발 종합반의 week 별 체크인 수를 세고 보기 좋게 정리해보기 -

 

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

 

 

+) group byorder by에 다수의 필드를 사용해야 할 때는 콤마를 이용한다.

 

ex) group by c.title, c2.week
      order by c.title, c2.week

 

 

 

 [ inner join, >= ]

 - 윗 문제에서 8월 1일 이후에 구매한 고객들만 골라내기 -

 

SELECT c.title, c2.week, count(*) as cnt from courses c
inner join checkins c2
on c.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 c.title, c2.week
order by c.title, c2.week

 

 

+) 8월 1일 이후에 구매한 고객의 데이터는 orders 테이블에 저장되어 있기 때문에,

   courses 테이블과 checkins 테이블 중 Key가 있는 checkins의 테이블에 orders의 테이블을 합친 후

   orders의 테이블에 속해있던 주문데이터에 where절로 8월 1일과 같거나 그 이상(>=)의 조건을 걸어

   출력값에 8월 1일 이후에 주문한 고객 데이터만 조회할 수 있도록 하였다.

 

 

 

 [ left join, where, between, count, round, alias ]

 - 7/10 ~ 7/19에 가입한 고객 중 포인트를 가진 고객의 수, 전체 수, 비율을 조회하기 -

 

SELECT count(point_user_id) as pnt_user, 
	   count(*) as total_user, 
	   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'

 

 

+) CountNull을 세지 않는다.

    예제처럼 round(필드값,2)를 해주면 소수점 둘째 자리까지 반올림이 되어 출력된다.