본문 바로가기

스파르타코딩클럽/SQL

SQL 문법정리

1. Select 쿼리문 

Select 쿼리문은 데이터베이스에서 '데이터를 선택해서 가져오겠다'는 의미입니다.

테이블과 필드(데이터) 로 구성됩니다.

Select * from 테이블명 어떤 테이블의 필드(데이터)를 모두 보여줘
Select 필드명 from 테이블명 어떤 테이블의 특정 필드를 보여줘

여러가지 기능

Distinct 중복 데이터 제외 Select Distincs(필드명) from 테이블명 어떤 필드의 데이터를 중복없이 표시
Count 개수 세기 Select Count(필드명) from 테이블명 어떤 필드의 데이터 개수를 표시
Limit 제한 Select * from 테이블명 limit 5 어떤 테이블의 데이터를 5개만 표시

2. Where 절

Where 절은, Select 쿼리문으로 가져올 데이터에 조건을 걸어주는 것을 의미합니다.

여러개의 조건을 걸고 싶을때는 and를 사용합니다.

Where 필드명 조건 원하는값 (and 원하는값) 어떤 필드에 특정 조건을 만족하는 값(데이터)를 보여줘

Where 절과 자주 같이쓰는 문법

'같지 않음' != where 필드명 != '1234'
'범위' between where 필드명 between '1' and '10'
'포함' in where 필드명 in (1,3)
'패턴' like where 필드명 like '%daum.net'

패턴 like 사용예시

where 필드명 like '%daum.net' 어떤 필드의 데이터 뒤쪽에 daum.net가 붙어있으면 표시
where 필드명 like '%daum%' 어떤 필드의 데이터의 중간에 daum이 포함되어 있으면 표시
where 필드명 like 'daum%' 어떤 필드의 데이터 앞에 daum이 포함되어 있으면 표시

3. Group by, Order by

  • Group by : 범주의 통계
  • Order by : 정렬,  desc : 내림차순
select name, count(*) from users
group by name;
order by count(*) desc;
  • 위 쿼리가 실행되는 순서: from → group by → select → order by
    1. from users: users 테이블 데이터 전체를 가져옵니다.
    2. group by name: users 테이블 데이터에서 같은 name을 갖는 데이터를 합쳐줍니다.
    3. select name, count(*): name에 따라 합쳐진 데이터가 각각 몇 개가 합쳐진 것인지 세어줍니다.
    4. 예) 이**, 이**, 김**, 김**, 박** 이렇게 데이터가 있었다면, 이는 2개, 김은 2개, 박**은 1개겠죠!
    5. order by count(*): 합쳐진 데이터의 개수에 따라 오름차순으로 정렬해줍니다.

4. 별칭 기능 Alias

  • 테이블명 뒤에 as를 붙여 별칭 추가
select * from orders o
where o.course_title = '앱개발 종합반'
  • 출력될 필드에 별칭 추가
select payment_method, count(*) as cnt from orders o
where o.course_title = '앱개발 종합반'
group by payment_method

count(*)가 아닌 cnt로 출력

 


5. Join

Join : 두 테이블의 공통된 정보 (key값)를 기준으로 테이블을 연결해서 한 테이블처럼 보는 것을 의미

Join의 종류

  • Left Join : A 테이블에 겹치는 필드(Key)를 기준으로 B테이블을 연결
  • Inner Join : A테이블과 B 테이블 모두 가지고 있는 데이터만 출력 (교집합)

inner join 예시

더보기

1) user_id를 key값으로 하여 orders 테이블과 users 테이블 연결

select * from orders o
inner join users u on o.user_id = u.user_id

2) user_id를 key값으로 하여 checkins 테이블과 users 테이블 연결

select * from checkins c
inner join users u on c.user_id = u.user_id

 

left join 예시

7월10일 ~ 7월19일에 가입한 고객 중, 포인트를 가진 고객의 숫자, 전체 숫자, 비율

더보기
select count(pu.user_id)as pnt_user_cnt,
           count(u.user_id)as tot_user_cnt,
           round(count(pu.user_id)/count(*),2) as ratio 
from users u 
left join point_users pu on pu.user_id = u.user_id 
where u.created_at BETWEEN "2020-07-10" and "2020-07-20"
  • 힌트1 → count 은 NULL을 세지 않는답니다!
  • 힌트2 → Alias(별칭)도 잘 붙여주세요!
  • 힌트3 → 비율은 소수점 둘째자리에서 반올림!

6. 결과물 합치기 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
)
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
)

4. 쿼리 안의 쿼리 Subquery

1) Where에 들어가는 Subquery

  • Subquery의 결과를 조건에 활용하는 방식으로 유용하게 사용
  • where 필드명 in (subquery)
더보기
  • 전체 유저의 포인트의 평균보다 큰 유저들의 데이터 추출하기
select * from point_users pu
where pu.point > 
(select avg(pu2.point) from point_users pu2)
  • 이씨 성을 가진 유저의 포인트의 평균보다 큰 유저들의 데이터 추출하기
select * from point_users pu
	where pu.point > 
(select avg(pu2.point) 
from point_users pu2 inner join users u 
    on pu2.user_id = u.user_id
    where u.name like '이%')

 

2) Select에 들어가는 Subquery

  • Select는 결과를 출력해주는 부분
  • 기존 테이블에 함께 보고싶은 통계 데이터를 손쉽게 붙이는 것에 사용
  • select 필드명, 필드명, (subquery) from ...
더보기
  • checkins 테이블에 course_id별 평균 likes수 필드 우측에 붙여보기
SELECT checkin_id, 
       course_id, 
       user_id, 
       likes,
       (SELECT round(avg(c2.likes),1)from checkins c2
       where c.course_id = c2.course_id) as course_avg
from checkins c
  • checkins 테이블에 과목명별 평균 likes수 필드 우측에 붙여보기
SELECT c.checkin_id, 
       cs.title,
       c.user_id, 
       c.likes,
       (SELECT round(avg(c2.likes),1) from checkins c2
       where c.course_id = c2.course_id) as course_avg
from checkins c
inner join courses cs 
on cs.course_id = c.course_id

 

 

3) From에 들어가는 Subquery

  • 내가 만든 Select와 이미 있는 테이블을 Join하고 싶을 때 사용
  • 가장 많이 사용되는 유형
더보기
  •  course_id별 like 개수에 전체 인원을 붙이고 퍼센트 및 강의 제목 나타내기
SELECT c.title, a.cnt_checkins, b.cnt_total, 
      (a.cnt_checkins/b.cnt_total) as ratio
from (
SELECT course_id, count(DISTINCT(user_id))as cnt_checkins  from checkins
group by course_id) a 
inner join(
SELECT course_id, count(*) as cnt_total from orders
group by course_id) b 
on a.course_id = b.course_id 
inner join courses c on a.course_id = c.course_id

5. With 절

서브쿼리를 사용하다 보면 헷갈리고 보기 힘들때 사용합니다. (보기 좋게)

select c.title,
       a.cnt_checkins,
       b.cnt_total,
       (a.cnt_checkins/b.cnt_total) as ratio
from
(
	select course_id, count(distinct(user_id)) as cnt_checkins from checkins
	group by course_id
) a
inner join
(
	select course_id, count(*) as cnt_total from orders
	group by course_id 
) b on a.course_id = b.course_id
inner join courses c on a.course_id = c.course_id

위에 쿼리와 아래의 쿼리의 결과는 같습니다

with table1 as (
	select course_id, count(distinct(user_id)) as cnt_checkins from checkins
	group by course_id
), table2 as (
	select course_id, count(*) as cnt_total from orders
	group by course_id
)

select c.title,
       a.cnt_checkins,
       b.cnt_total,
       (a.cnt_checkins/b.cnt_total) as ratio
from table1 a inner join table2 b on a.course_id = b.course_id
inner join courses c on a.course_id = c.course_id

사용법 : with 별칭 as (서브쿼리)


6. 문자열

  • 문자열 쪼개기 ( SUBSTRING_INDEX )
select user_id, email, SUBSTRING_INDEX(email, '@', 1) from users

SUBSTRING_INDEX(필드명, '@'를 기준으로, 첫번째(앞) 조각을 표시한다.

select user_id, email, SUBSTRING_INDEX(email, '@', -1) from users

SUBSTRING_INDEX(필드명, '@'를 기준으로, 마지막(뒤) 조각을 표시한다.

 

  • 문자열 일부만 출력하기 ( SUBSTRING ) 
  • SUBSTRING(문자열, 출력을 하고싶은 첫 글자의 위치, 몇개의 글자를 출력하고 싶은지)
select order_no, created_at, substring(created_at,1,10) as date from orders

SUBSTRING(필드명(문자열),첫 글짜는 첫 번째 글자, 첫번째 글자부터 10개의 글자 출력)

select substring(created_at,1,10) as date, count(*) as cnt_date from orders
group by date

7. 조건문 Case 

조건에 따라 원하는 값을 출력하고 싶다면 Case

  • pu.point 가 10000보다 클 때 '잘 하고 있어요!' 출력, else(아니라면) '조금 더 달려주세요!' 출력, 마침(End) as '구분'
select pu.point_user_id, pu.point,
case 
when pu.point > 10000 then '잘 하고 있어요!'
else '조금 더 달려주세요!'
END as '구분'
from point_users pu;