[수업 목표]
[복습]
CASE
WHEN 조건1 THEN 값(수식)1
WHEN 조건2 THEN 값(수식)2
ELSE 값(수식)3
END
SELECT column1, special_column
FROM
(/*subquery*/
SELECT column1, column2 special_column
FROM table1
) a
※ 단일행 서브쿼리(SingleRow Subquery): 하나의 행만 리턴하기 때문에 단일행 비교 연산자(=, <, >, <>)만 사용
SELECT column1, column2
FROM table1
WHERE column1 = (SELECT col1 FROM table2)
SELECT order_id, restaurant_name, food_preparation_time
FROM (
SELECT order_id, restaurant_name, food_preparation_time
FROM food_orders
) a
SELECT order_id, restaurant_name, IF(over_time>0, over_time, 0) over_time
FROM (
SELECT order_id, restaurant_name, food_preparation_time-25 over_time
FROM food_orders
) a
a. 어떤 테이블에서 데이터를 뽑을 것인가 → FROM food_orders
b. 어떤 컬럼을 이용할 것인가 → restaurant_name, price, quantity
c. 어떤 조건을 지정해야 하는가 → 조건 없음
d. 어떤 함수(수식) → AVG(price/quantity), CASE, GROUP BY
SELECT restaurant_name,
price_per_plate*ratio_of_add "수수료"
FROM (
SELECT restaurant_name,
CASE
WHEN price_per_plate < 5000 THEN 0.0005
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,
FROM (
SELECT restaurant_name,
AVG(price/quantity) price_per_plate
FROM food_orders
GROUP BY 1
) a
) b
💡 price_per_plate between 5000 and 19999
대신에 price_per_plate >= 5000 AND price_per_plate < 20000
라고 쓰면 안 되나? → 됨!
price BETWEEN a AND b
는 price >= a AND price <= b
와 동일한 조건임
강의에서는 두 개의 방식 모두 보여주려는 것으로 실제로는 한 개의 방식으로 통일해서 작성하면 됨 (다만 작성할 때에는 조건 범위에 유의할 것)
SELECT restaurant_name,
CASE
WHEN avg_time <= 20 THEN '20분 이하'
WHEN avg_time > 20 AND avg_time <= 30 THEN '20분 초과 30분 이하'
WHEN avg_time > 30 THEN '30분 초과'
END time_segment
FROM (
SELECT restaurant_name,
SUBSTRING(addr, 1, 2) sido,
AVG(delivery_time) avg_time
FROM food_orders
GROUP BY 1, 2
) a
💡 MySQL에서는 쌍따옴표와 홑따옴표를 엄격하게 구분하지 않는데 다른 데이터베이스에서는 쌍따옴표와 홑따옴표의 사용을 구분해서 사용하므로 구분하는 편이 좋음
→ 홑따옴표: 문자열 값을 나타내는 데 사용. 문자열 안에는 모든 문자가 포함될 수 있음.
→ 쌍따옴표: 식별자(table name, column name 등)에 사용될 때 주로 활용.
※ 쌍따옴표 내부에 있는 문자는 대소문자를 구분하여 처리되며 이는 대소문자를 구분하지 않는 기본적인 데이터베이스 동작과는 다름
a. 음식점 수 5개 이상, 주문 수 30개 이상 → 수수료 0.05%
b. 음식점 수 5개 이상, 주문 수 30개 미만 → 수수료 0.08%
c. 음식점 수 5개 미만, 주문 수 30개 이상 → 수수료 1%
d. 음식점 수 5개 미만, 주문 수 30개 미만 → 수수료 2%
SELECT cuisine_type,
total_quantity,
count_of_restaurant,
CASE
WHEN count_of_restaurant >= 5 AND total_quantity >= 30 THEN 0.0005
WHEN count_of_restaurant >= 5 AND total_quantity < 30 THEN 0.0008
WHEN count_of_restaurant < 5 AND total_quantity >= 30 THEN 0.01
WHEN count_of_restaurant < 5 AND total_quantity < 30 THEN 0.02
END ratio_of_add
FROM (
SELECT cuisine_type,
SUM(quantity) total_quantity,
COUNT(DISTINCT restaurant_name) count_of_restaurant
FROM food_orders
GROUP BY 1
) a
💡 DISTINCT restaurant_name
→ 주문 내역의 음식점 이름이 같은 경우 한 번만 세는 것
→ “한 번이라도 주문이 들어간 음식점 수” (한 곳에 여러 번 주문했을 때 음식점 수를 count한다면 distinct로 중복값을 제거해주는 게 맞음)
SELECT restaurant_name,
CASE
WHEN sum_of_quantity<=5 THEN 0.1
WHEN sum_of_quantity>15 AND sum_of_price>=300000 THEN 0.005
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
고객 ID | 주문 번호 | 식당 이름 | 고객 이메일 |
---|---|---|---|
1 | 10 | A | |
2 | 11 | B | |
3 | 12 | C | |
4 | 13 | D |
고객 ID | 전화번호 | 이메일 | 연령 |
---|---|---|---|
1 | 0000-0000 | abc@naver.com | 20 |
2 | 1111-1111 | def@kakao.com | 25 |
3 | 2222-2222 | ghi@gmail.com | 30 |
4 | 3333-3333 | jkl@naver.com | 35 |
주문 번호 | 식당 이름 | 고객 ID | 전화번호 | 이메일 | 연령 |
---|---|---|---|---|---|
10 | A | 1 | 0000-0000 | abc@naver.com | 20 |
11 | B | 2 | 1111-1111 | def@kakao.com | 25 |
12 | C | 3 | 2222-2222 | ghi@gmail.com | 30 |
13 | D | 4 | 3333-3333 | jkl@naver.com | 35 |
14 | D | 5 |
--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.공통컬럼명
💡 공통 컬럼은 묶어주기 위한 ‘공통 값’이기 때문에 컬럼명 달라도 괜찮음
(예) 주문정보 테이블에는 ‘고객 ID’, 고객정보 테이블에는 ‘고객 아이디’라는 컬럼명일 경우 주문정보.고객ID = 고객정보.고객아이디
와 같이 묶을 수 있음
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
a. 조회 컬럼: 주문 번호, 식당 이름, 주문 가격, 결제 수단, 수수료율
b. 결제 정보가 없는 경우도 포함하여 조회
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
a. 조회 컬럼: 고객 이름, 연령, 성별, 주문 식당
b. 고객명으로 정렬, 중복 없도록 조회
SELECT c.name ,
c.age ,
c.gender ,
fo.restaurant_name
FROM food_orders fo LEFT JOIN customers c ON fo.customer_id = c.customer_id
ORDER BY c.name
※ null 값을 제거하려면
SELECT c.name ,
c.age ,
c.gender ,
fo.restaurant_name
FROM food_orders fo LEFT JOIN customers c ON fo.customer_id = c.customer_id
WHERE c.name IS NOT NULL // null값 제거
ORDER BY c.name
a. 조회 컬럼: 주문 번호, 식당 이름, 주문 가격, 수수료율, 수수료
b. 수수료율이 있는 경우만 조회
SELECT fo.order_id,
fo.restaurant_name,
fo.price,
p.vat,
fo.price*p.vat "수수료율"
FROM food_orders fo INNER JOIN payments p ON fo.order_id = p.order_id
a. 조회 컬럼: 음식 타입, 원래 가격, 할인 적용 가격, 할인 가격
b. 할인: (나이-50)*0.005
c. 고객 정보가 없는 경우도 포함하여 조회, 할인 금액이 큰 순서대로 정렬
SELECT cuisine_type,
SUM(price) "원래 가격",
SUM(price)-SUM(discount_price) "할인 적용 가격",
SUM(discount_price) "할인 가격"
FROM
(
SELECT fo.cuisine_type,
price,
price*((c.age-50)*0.005) discount_price
FROM food_orders fo INNER JOIN customers c ON fo.customer_id = c.customer_id
WHERE c.age >= 50
) t
GROUP BY 1
ORDER BY 4 DESC
SELECT restaurant_name,
CASE
WHEN price <=5000 THEN 'price_group1'
WHEN price >5000 AND price <=10000 THEN 'price_group2'
WHEN price >10000 AND price <=30000 THEN 'price_group3'
WHEN price >30000 THEN 'price_group4'
END price_group,
CASE
WHEN age <30 THEN 'age_group1'
WHEN age BETWEEN 30 AND 39 THEN 'age_group2'
WHEN age BETWEEN 40 AND 49 THEN 'age_group3'
ELSE 'age_group4'
END age_group
FROM
(
SELECT fo.restaurant_name,
AVG(price) price,
AVG(age) age
FROM food_orders fo INNER JOIN customers c ON fo.customer_id = c.customer_id
GROUP BY 1
) t
ORDER BY 1