SQL은 코드가 아니라 데이터베이스에 요청하는 언어
따라서 어떤 요청을 할 지를 생각해봐야한다.
select
데이터를 가져오는 기본 명령어, 데이터를 조회하는 모든 쿼리에 사용
from
데이터를 가져올 테이블을 특정해주는 문법
*
모든 컬럼을 가져와 준다는 의미
예시
select *
from food_orders
테이블의 모든 컬럼이 필요하지 않을 때, 필요한 것만 선택하여 조회 가능
예시
select 컬럼1, 컬럼2
from 테이블
방법1
컬럼 1 as 별명 1
방법2
컬럼2 별명2
영문 언더바 별명만 적는다
특수문자 한글 큰 따옴표 안에 적어준다 / "별명"
데이터 중 특정 조건을 필터링할 때, where 문법을 잉요해 전체 데이터 중 원하는 데이터만 필터링이 가능하다.
예시
select *
from customers
where age=21
숫자가 아닌 문자도 가능하다. 문자를 사용할 때는 '작은 따옴표'를 씌운다.

select *
from food_orders
where price between 20000 and 30000
select *
from customers
where age in (15,21,31)
select *
from food_orders
where restaurant_name like 'B%'
여러 조건을 적용할 때 사용되는 연산

예시
select *
from food_orders
where cuisine_type='Korean' and price>=30000
: 데이터를 조회하는 SQL 기본 구조를 활용해 숫자 계산 및 정렬 사용해보기
✅ 기본 연산
연산자 종류 : +(더하기) -(빼기) *(곱하기) /(나누기)
함수 종류 : SUM, AVG
사용할 때는 데이터의 범위가 아닌 계산할 컬럼을 적어야 한다.
select sum(food_preparation_time) total_food_preparation_time,
avg(delivery_time) avg_food_preparation_time
from food_orders
✅ 전체 데이터의 갯수 구하기
함수종류 : COUNT(컬럼 / 1 / *)
몇 개의 값을 가지고 있는 지 구할 때에는 distinct 를 사용한다.
select count(1) count_of_orders,
count(distinct customer_id)
count_of_customers
from food_orders
✅ 데이터의 범위, 최솟값과 최댓값 구하기
함수종류: MIN, MAX (컬럼)
조회하는 데이터의 최솟값, 최댓값으로 범위도 구할 수 있다 !
select min(price) min_price,
max(price) max_price
from food_orders
✅ 카테고리 별 숫자 연산을 간단하게.
기본구조 : 카테고리 컬럼 지정, GROUP BY 작성
select cuisine_type, sum(price) sum_of_price
from food_orders
group by cuisine_type
✅ 조회한 결과를 원하는 순서대로 정렬하기
정렬 종류 : 오름차순(생략), 내림차순 desc
기본구조 : 카테고리 컬럼 지정, ORDER BY 작성
select cuisine_type, sum(price) sum_of_price
from food_orders
group by cuisine_type
order by sum(price)
사용 함수 : REPLACE, SUBSTRING, CONCAT
특정 문자를 다른 문자로 바꿀 때
replace (바꿀 컬럼, 현재 값, 바꿀 값)
select restaurant_name "원래 상점명",
replace(restaurant_name, 'Blue', 'Pink') "바뀐 상점명"
from food_orders
where restaurant_name like '%Blue Ribbon%'
원하는 문자만 남기기
substring(substr) (조회할 컬럼, 시작위치, 글자 수)
select addr "원래 주소",
substr(addr, 1, 2) "시도"
from food_orders
where addr like '%서울특별시%'
여러 컬럼의 문자를 합치기
붙일 수 있는 문자의 종류 : 컬럼, 한글, 영어, 숫자, 특수문자
concat(붙이고 싶은 값 1, 2, 3, ....)
select restaurant_name "원래 이름",
addr "원래 주소",
concat('[', substring(addr, 1, 2), '] ', restaurant_name) "바뀐 이름
from food_orders
where addr like '%서울%'
흐름 정리
1. 어떤 테이블에서 데이터를 뽑을 것인가
2. 어떤 컬럼을 이용할 것인가
3. 어떤 조건을 지정해야 하는가
4. 어떤 함수(수식)를 이용해야 하는가
예시
[지역(시도)] 음식점이름 (음식종류) 컬럼을 만들고, 총 주문건수 구하기
구문
1.
어떤 테이블에서 데이터를 뽑을 것인가 → from food_orders
2.
어떤 컬럼을 이용할 것인가 → addr, restaurant_name, cuisine_type,order_id
3.
어떤 조건을 지정해야 하는가 → X
4.
어떤 함수 (수식) 을 이용해야 하는가 → count(1), substring(addr, 1,2),concat(’[’, 뽑은시도, ‘] ‘, restaurant_name, ‘ (’, cuisine_type, ‘)’)
합치기
select concat('[', substring(addr, 1, 2), '] ', restaurant_name, ' (', cuisine
count(1) "주문건수"
from food_orders
group by 1
사용함수 : if, case
내가 원하는 범주를 조건으로 주고, 해당 범주에 적용하고 싶은 것을 지정한다.
원하는 조건에 충족할 때 적용할 방법과 아닌 방법을 지정하기
IF(조건, 조건을 충족할 때, 조건을 미충족할 때)
select restaurant_name,
cuisine_type "원래 음식 타입",
if(cuisine_type='Korean', '한식', '기타') "음식 타입"
from food_orders
조건을 여러가지 지정하고 싶을 때
CASE when 조건 1 then 값(수식)1
when 조건 2 then 값(수식)2
else 값(수식) 3
end
select restaurant_name,
addr,
case when addr like '%경기도%' then '경기도'
when addr like '%특별%' or addr like '%광역%' then substrin
else substring(addr, 1, 2)
end "변경된 주소"
from food_orders
조건을 사용할 수 있는 경우들
1. 새로운 카테고리 만들기
2. 연산식을 적용할 조건 지정하기
3. 다른 문법 안에서 적용하기
--숫자로 변경
cast(if(rating='Not given', '1', rating) as decimal)
--문자로 변경
concat(restaurant_name, '-', cast(order_id as char))
select column1, special_column
from
( /* subquery */
select column1, column2 special_column
from table1
) a
select column1, column2
from table1
where column1 = (select col1 from table2)
실습
음식점의 평균 단가별 segmentation을 진행하고, 그룹에 따라 수수료 연산하기
흐름 정리
1.어떤 테이블에서 데이터를 뽑을 것인가 → 주문 테이블
2.어떤 컬럼을 이용할 것인가 → 식당 이름, 주문 금액, 주문 수량
3.어떤 조건을 지정해야 하는가 → X
4.어떤 함수 (수식) 을 이용해야 하는가 → 평균 구하는 식, 카테고리에 따라 연산, 조건문
쿼리 작성
select restaurant_name,
price_per_plate*ratio_of_add "수수료"
from
(
select restaurant_name,
case when price_per_plate<5000 then 0.005
when price_per_plate between 5000 and 19999 then 0.01
when price_per_plate between 20000 and 29999 then 0.02
else 0.03 end ratio_of_add,
price_per_plate
from
(
select restaurant_name, avg(price/quantity) price_per_plate
from food_orders
group by 1
) a
) b
실습
음식점의 총 주문수량과 주문 금액을 연산하고, 주문 수량을 기반으로 수수료 할인율 구하기
✅ 할인 조건
흐름 정리
1. 어떤 테이블에서 데이터를 뽑을 것인가 → 주문 테이블
2. 어떤 컬럼을 이용할 것인가 → 음식점 이름, 주문 수량, 주문 금액
3. 어떤 조건을 지정해야 하는가 → X
4. 어떤 함수 (수식) 을 이용해야 하는가 → 합계를 구하는 기능, 조건문
쿼리 작성
select restaurant_name,
case when sum_of_quantity<=5 then 0.1
when sum_of_quantity>15 and sum_of_price>=300000 then 0.0
else 0.01 end ratio_of_add
from
(
select restaurant_name,
sum(quantity) sum_of_quantity,
sum(price) sum_of_price
from food_orders
group by 1
) a
필요한 데이터가 서로 다른 테이블에 있을 때
두 테이블이 공통으로 갖고 있는 컬럼을 기준으로 테이블을 합쳐 필요한 데이터를 조회할 수 있도록 해준다.

LEFT JOIN
공통 컬럼을 기준으로, 하나의 테이블에 값이 없더라도 모두 조회되는 경우
INNER JOIN
공통 컬럼을 기준으로, 두 테이블 모두에 있는 값만 조회되는 경우
-- LEFT JOIN
select 조회 할 컬럼
from 테이블1 a left join 테이블2 b on a.공통컬럼명=b.공통컬럼명
-- INNER JOIN
select 조회 할 컬럼
from 테이블1 a inner join 테이블2 b on a.공통컬럼명=b.공통컬럼명
실습
한국 음식의 주문별 결제 수단과 수수료율을 조회하기
(조회 컬럼 : 주문 번호,식당 이름, 주문 가격, 결제 수단, 수수료율)
결제 정보가 없는 경우도 포함하여 조회
흐름 작성
1. 어떤 테이블에서 데이터를 뽑을 것인가 → from food_orders, payments
2. 어떤 컬럼을 이용할 것인가 → order_id, restaurant_name, price, pay_type, vat
3. 어떤 조건을 지정해야 하는가 → where cuisine_type=’Korean’
4. 어떤 함수 (수식) 을 이용해야 하는가 → left join payments (on order_id)
쿼리 작성
select a.order_id,
a.restaurant_name,
a.price,
b.pay_type,
b.vat
from food_orders a left join payments b on a.order_id=b.order_id
where cuisine_type='Korean'
사용할 수 없는 데이터가 들어있거나, 값이 없는 경우에 사용한다.
값의 제외 null 이용
예시
select a.order_id,
a.customer_id,
a.restaurant_name,
a.price,
b.name,
b.age,
b.gender
from food_orders a left join customers b on a.customer_id=b.customer_id
where b.customer_id is not null
값의 변경 coalesce(컬럼, 대체값)
예시
select a.order_id,
a.customer_id,
a.restaurant_name,
a.price,
b.name,
b.age,
coalesce(b.age, 20) "null 제거",
b.gender
from food_orders a left join customers b on a.customer_id=b.customer_id
where b.age is null
예를 들어, 주문고객의 나이가 2세라거나, 결제일자가 1970년도 등일 때
조건문으로 값의 범위를 지정한다
예시
select customer_id, name, email, gendor, age,
case when age<15 then 15
when age>80 then 80
else age end "범위를 지정해준 age"
from customers
15세 미만은 15세로, 80세 초과는 80세로 대체된 것을 확인할 수 있다.
max() 활용
2개 이상의 기준으로 데이터를 집계할 때, 보기 쉽게 배열하여 보여주는 것

실습
음식점 별 시간 별 주문건 수 확인하기 (15-20시 사이, 20시 주문건 수 기준 내림차순)
select a.restaurant_name,
substring(b.time, 1, 2) hh,
count(1) cnt_order
from food_orders a inner join payments b on a.order_id=b.order_id
where substring(b.time, 1, 2) between 15 and 20
group by 1, 2
select restaurant_name,
max(if(hh='15', cnt_order, 0)) "15",
max(if(hh='16', cnt_order, 0)) "16",
max(if(hh='17', cnt_order, 0)) "17",
max(if(hh='18', cnt_order, 0)) "18",
max(if(hh='19', cnt_order, 0)) "19",
max(if(hh='20', cnt_order, 0)) "20"
from
(
select a.restaurant_name,
substring(b.time, 1, 2) hh,
count(1) cnt_order
from food_orders a inner join payments b on a.order_id=b.order_id
where substring(b.time, 1, 2) between 15 and 20
group by 1, 2
) a
group by 1
order by 7 desc
각 행의 관계를 정의하기 위한 함수, 그룹 내의 연산을 쉽게 만든다.
예시
한식 식당 중, 주문 건수가 많은 순으로 순위 매기기
한식 식당 전체 주문 건수 중에서 A식당이 차지하는 비율
window_function(argument) over (partition by 그룹 기준 컬럼 order by 정렬 기준)
window_function : 기능 명을 사용해줍니다. (sum, avg 와 같이 기능명이 있습니다)
argument : 함수에 따라 작성하거나 생략합니다.
partition by : 그룹을 나누기 위한 기준입니다. group by 절과 유사하다고 생각해주시면 됩니다.
order by : window function 을 적용할 때 정렬 할 컬럼 기준을 적어줍니다.
N번째까지의 대상을 조회하고 싶을 때
특정 기준으로 순위를 매겨주는 기능!
실습
음식 타입 별로 주문 건수가 가장 많은 상점 3개씩 조회하기
select cuisine_type,
restaurant_name,
order_count,
rn "순위"
from
(
select cuisine_type,
restaurant_name,
rank() over (partition by cuisine_type order by order_count desc) rn,
order_count
from
(
select cuisine_type, restaurant_name, count(1) order_count
from food_orders
group by 1, 2
) a
) b
where rn<=3
order by 1, 4
전체에서 차지하는 비율, 누적 합을 구할 때
합계를 구하는 기능이지만, 누적 합을 구하거나 카테고리 별 합계 컬럼과 원본 컬럼을 함께 이용할 때 유용하다 !
실습
각 음식점의 주문건이 해당 음식 타입에서 차지하는 비율을 구하고, 주문 건이 낮은 순으로 정렬했을 때 누적합 구하기
select cuisine_type,
restaurant_name,
order_count,
sum(order_count) over (partition by cuisine_type) sum_cuisine_type,
sum(order_count) over (partition by cuisine_type order by order_count, restau
from
(
select cuisine_type, restaurant_name, count(1) order_count
from food_orders
group by 1, 2
) a
sql의 연산은 날짜도 가능하다. 데이터에 날짜를 지정하거나 조건에 날짜를 사용해야 할 때 활용해보자.
select date(date) date_type,
date
from payments
select date(date) date_type,
date_format(date(date), '%Y') "년",
date_format(date(date), '%m') "월",
date_format(date(date), '%d') "일",
date_format(date(date), '%w') "요일"
from payments
실습
년도, 월 별 주문건수를 구해 3월 조건으로 지정하고, 년도별로 정렬하기
select date_format(date(date), '%Y') y,
date_format(date(date), '%m') m,
count(1) order_count
from food_orders a inner join payments b on a.order_id=b.order_id
where date_format(date(date), '%m')='03'
group by 1, 2
order by 1