관련 설명
https://velog.io/@dyllis_lin/MySQL-%EA%B8%B0%EB%A1%9D3
SELECT restaurant_name AS "원래 이름"
, REPLACE(restaurant_name, 'Blue', 'Pink') AS "바뀐 이름"
FROM food_orders fo
WHERE restaurant_name LIKE '%Blue Ribbon%';
- LIKE의 사용
% -> 모든 문자 대체
_ -> 언더스코어 개수 만큼 모든 문자 대체(한 글자)
- %Blue Ribbon%
-> Blue Ribbon이 포함된 ROW를 찾을 때
-> Blue Ribbon 앞뒤에 무슨 글자가 오든지 간에 'Blue Ribbon'이 포함된 ROW를 출력하고 싶을 때
- Blue Ribbon%
-> 'Blue Ribbon'으로 시작하는 문자가 있는 ROW를 찾을 때
- %Blue Ribbon
-> 'Blue Ribbon'으로 끝나는 문자가 있는 ROW를 찾을 때
- _Blue Ribbon%
-> 한 문자 뒤에 'Blue Ribbon'이 있는 Row를 찾을 때(Blue Ribbon 뒤에는 어떤 글자가 오든 상관없음)
- _Blue Ribbon__
-> 한 문자 뒤에 'Blue Ribbon'이 오고, 그 'Blue Ribbon'뒤에는 2개의 문자가 오는 Row를 찾을 때
결론 : 조합하기 나름
SELECT addr AS "원래 주소"
, REPLACE(addr, '문곡리', '문가리') AS "바뀐 주소"
FROM food_orders fo
WHERE addr LIKE '%문곡리%';
SELECT addr AS "원래 주소"
, SUBSTR(addr, 1, 2) AS "바뀐 주소"
FROM food_orders fo
WHERE addr LIKE '%서울특별시%';
로직
1. 필요 컬럼 : 식당 이름, 주소
2. 조건 : 서울 지역 -> WHERE addr LIKE '%서울%';
3. 필요 수식 : '[서울] 음식점명' 형태로 만들기
-> CONCAT('[', SUBSTR(addr, 1, 2), ']' ' ', restaurant_name)
SELECT restaurant_name AS "원래 이름"
, addr AS "원래 주소"
, CONCAT('[', SUBSTR(addr, 1, 2), ']' ' ', restaurant_name) AS "바뀐이름"
FROM food_orders fo
WHERE addr LIKE '%서울%';
로직
1. 필요 컬럼 : 주문 금액, 음식 타입, 주소
2. 조건 : 서울 지역
3. 필요 수식 : AVG, SUBSTR
SELECT SUBSTR(addr, 1, 2) AS "지역"
, cuisine_type AS "음식 종류"
, AVG(price) AS "평균 금액"
FROM food_orders fo
WHERE addr LIKE '%서울%'
GROUP BY SUBSTR(addr, 1, 2), cuisine_type;
로직
1. 필요 컬럼 : 이메일 주소, 고객 번호, 나이
2. 조건 : 없음
3. 필요 수식 : SUBSTR, AVG, COUNT
SELECT SUBSTR(email, 10) AS "이메일 도메인"
, COUNT(customer_id) AS "고객 수"
, AVG(age) AS "평균 연령"
FROM customers c
GROUP BY SUBSTR(email, 10);
- 도메인 별로 묶어야 하기 때문에 @ 이후의 도메인 주소(xxx.com이나 xxx.net 등)만 뽑아야 한다.
- 'SUBSTR(조회 할 컬럼, 시작 위치, 시작 위치로부터의 글자 수)' 에서 시작 위치로부터의 글자 수를 생략하면, 시작 위치로부터 해당 문자열의 끝까지 반환한다.
로직
1. 필요 컬럼 : 주소, 음식점 이름, 음식 종류, 주문 번호
2. 조건 : 없음
3. 필요 수식 : SUBSTR, CONCAT, COUNT
SELECT CONCAT('[', SUBSTR(addr, 1, 2), '] ', restaurant_name, ' (', cuisine_type, ')')
, COUNT(1) AS "주문 건수"
FROM food_orders fo
GROUP BY 1;
SELECT restaurant_name AS "식당 이름"
, cuisine_type AS "원래 음식 타입"
, IF(cuisine_type = 'Korean', '한식', '기타') AS "음식 타입"
FROM food_orders fo;
SELECT addr AS "원래 주소"
, IF(addr LIKE '%평택군%', REPLACE(addr, '문곡리', '문가리'), addr) AS "바뀐 주소"
FROM food_orders fo
WHERE addr LIKE '%문곡리%';
- '문곡리'가 평택에만 해당될 때, 평택 '문곡리'만 '문가리'로 수정하기
-> IF(addr LIKE '%평택군%', REPLACE(addr, '문곡리', '문가리'), addr) AS "바뀐 주소"
SELECT SUBSTRING(IF(email LIKE '%gmail%',
REPLACE(email, 'gmail', '@gmail'), email), 10) AS "이메일 도메인"
, COUNT(customer_id) AS "고객 수"
, AVG(age) AS "평균 연령"
FROM customers c
GROUP BY 1;
SELECT restaurant_name AS "식당 이름"
, cuisine_type AS "원래 음식 타입"
, CASE WHEN cuisine_type = 'Korean' THEN '한식'
WHEN cuisine_type IN ('Japanese', 'Chinese') THEN '아시안'
ELSE '기타'
END
FROM food_orders fo;
IN 대신 OR도 가능핟다.
-> WHEN cuisine_type = 'Japanese' OR cuisine_type = 'Chinese' THEN '아시안'
SELECT order_id
, price AS "가격"
, quantity AS "수량"
, CASE WHEN quantity = 1 THEN price
WHEN quantity >= 2 THEN price/quantity
END "음식 단가"
FROM food_orders fo;
select restaurant_name,
addr,
case when addr like '%경기도%' then '경기도'
when addr like '%특별시%' or addr like '%광역시%' then substring(addr, 1, 5)
else substring(addr, 1, 2) end "변경된 주소"
from food_orders;
이 문제 풀 때 진짜 애먹었다.
'특별시' 혹은' 광역시'일 때는 붙여서
이 부분에서 생각이 계속 꼬였다. 처음에는 OR은 생각도 못하고 IN을 쓰려 했는데 뭔가 더 복잡해지는 기분이었다.
그리고 '붙인다' 라는 말에 갇혀서 생각의 회로가 계속 진짜 요상한 방향으로 튀어서
-> + 연산자로 계속 문자열 연결 못하나 -> 만약 되도 어떻게 연결할건데? 무한반복..........
게다가, (addr, 1, 5)는 생각지도 못했다.
돌아보고 나니까 당연히(?) IN으로도, OR로도 쓸 수 있었다. 정답 보고 헉 했다. 정말...........
어쨌거나 IN이나 OR 둘다 사용 가능하다.
- IN의 경우
-> WHEN addr IN ('%특별시%', '%광역시%') THEN SUBSTR(addr, 1, 5)- OR의 경우
-> WHEN addr LIKE '%특별시%' OR addr LIKE '%광역시%'%') THEN SUBSTR(addr, 1, 5)
그리고 내가 쓴 코드.........
-> WHEN addr LIKE IN('%특별시%', '%광역시%') THEN CONCAT(SUBSTR(addr, 1, 2), '특별시')
아까 언급했듯이 '붙여서'라는 단어에 매몰돼서 <붙인다 -> 연결 -> CONCAT 사용 해야만한다!> 라는 사고흐름으로 이어졌다.
근데 가만 생각해 보니까 CONCAT쓰면 쿼리가 더 지저분해 질 것 같다.(아마도...?) CONCAT을 사용해서 쿼리를 짤 수 있을것 같기는 한데, 딱 떠오르지는 않는다. 이미 SUBSTR 써서 짠 쿼리를 봐서 그런가 더욱더 생각 안남.
아무튼 진짜 대 혼 종. 그냥 CONCAT이든 SUBSTR이든 LIKE, IN, OR 모두 제대로 된 개념이 안 잡혀있던 것이었다. 그래도 아직 3일차니까 문제 많이 풀어서 체화 시키는 수 밖에 없을 듯....
로직
1. 필요 컬럼 : 이름, 나이, 성별
2. 조건 : 나이 10세 이상, 30세 미만 -> WHERE age BETWEEN 10 AND 29
3. 필요 수식 : 조건문 -> CASE WHEN ... END
SELECT name AS "이름"
, gender AS "성별"
, age
, CASE WHEN (age BETWEEN 10 AND 29) AND gender = 'male' THEN "10대 남자"
WHEN (age BETWEEN 10 AND 29) AND gender = 'female' THEN "10대 여자"
WHEN (age BETWEEN 20 AND 29) AND gender = 'male' THEN "20대 남자"
WHEN (age BETWEEN 20 AND 29) AND gender = 'female' THEN "20대 여자"
END AS "그룹"
FROM customers c
WHERE age BETWEEN 10 AND 29;
(가격 = 5000, 15000, 그 이상)
로직
1. 필요 컬럼 : 주문 금액, 주문 수량, 음식 종류
2. 조건 : 없음
3. 필요 수식 : 조건문 -> CASE WHEN ... END
SELECT restaurant_name AS "식당 이름"
, price/quantity "단가"
, cuisine_type "식당 타입"
, CASE WHEN (price/quantity < 5000) AND cuisine_type ='Korean' THEN '한식1'
WHEN (price/quantity BETWEEN 5000 AND 15000) AND cuisine_type ='Korean' THEN '한식2'
WHEN (price/quantity > 15000) AND cuisine_type ='Korean' THEN '한식3'
WHEN (price/quantity < 5000) AND cuisine_type IN ('Japanese', 'Chinese', 'Thai', 'Vietnamese', 'Indian') THEN '아시아식1'
WHEN (price/quantity BETWEEN 5000 AND 15000) AND cuisine_type IN ('Japanese', 'Chinese', 'Thai', 'Vietnamese', 'Indian') THEN '아시아식2'
WHEN (price/quantity > 15000) AND cuisine_type IN ('Japanese', 'Chinese', 'Thai', 'Vietnamese', 'Indian') THEN '아시아식3'
WHEN (price/quantity < 5000) AND cuisine_type NOT IN ('Korean', 'Japanese', 'Chinese', 'Thai', 'Vietnamese', 'Indian') THEN '기타1'
WHEN (price/quantity BETWEEN 5000 AND 15000) AND cuisine_type NOT IN ('Korean', 'Japanese', 'Chinese', 'Thai', 'Vietnamese', 'Indian') THEN '기타2'
WHEN (price/quantity > 15000) AND cuisine_type NOT IN ('Korean', 'Japanese', 'Chinese', 'Thai', 'Vietnamese', 'Indian') THEN '기타3'
END AS "식당 그룹"
FROM food_orders;
로직
1. 필요 컬럼 : 식당 이름, 주문 번호, 지역 , 배달 시간, 주문 금액
2. 조건 : 없음
3. 필요 수식 : 조건문 -> CASE, IF
SELECT
restaurant_name AS "식당 이름"
, order_id AS "주문 번호"
, delivery_time AS "배달 시간"
, price AS "가격"
, addr AS "주소"
CASE
WHEN addr LIKE '%서울%' THEN
CASE
WHEN delivery_time > 25 AND delivery_time <= 30 THEN (price * 1.1) + (price * 0.05)
WHEN delivery_time > 30 THEN (price * 1.1) + (price * 0.10)
ELSE price * 1.1
END
ELSE
CASE
WHEN delivery_time > 25 AND delivery_time <= 30 THEN price + (price * 0.05)
WHEN delivery_time > 30 THEN price + (price * 0.10)
ELSE price
END
END AS "수수료 포함 총 금액"
FROM
food_orders;
구조
CASE1
WHEN (주소가 서울 일 때,)
CASE 1-1
WHEN 배달시간이 25분 초과인 경우
WHEN 배달시간이 30분 초과인 경우
ELSE 그 외의 경우
END
ELSE (주소가 서울이 아닐 때,)
CASE 1-2
WHEN 배달시간이 25분 초과인 경우
WHEN 배달시간이 30분 초과인 경우
ELSE 그 외의 경우
END
END
중첩 CASE문 처음 써봄.... 뭔가 더 깔끔하고 간결하게 표현 할 수 있는 방법은 없나? 싶었는데 나한테는 이게 최선이었다. 사실 이게 맞는지도 모르겠음. 틀렸을 가능성 매우 농후.
로직
1. 필요 컬럼 : 주문 수량, 주문 시기
2. 조건 : 없음
3. 필요 수식 : 조건문 -> CASE, IF
SELECT order_id AS "주문 번호"
, price AS "가격"
, quantity AS "수량"
, day_of_the_week AS "구분"
, IF(day_of_the_week = 'Weekday', 3000, 3500)
* IF(quantity <= 3, 1, 1.2) AS "할증료"
FROM food_orders fo;
SELECT order_id AS "주문 번호"
, restaurant_name AS "식당 이름"
, delivery_time AS "배달 시간"
, day_of_the_week AS "구분"
, CASE WHEN day_of_the_week = 'Weekday' AND delivery_time >= 25 THEN 'Late'
WHEN day_of_the_week = 'Weekend' AND delivery_time >= 30 THEN 'Late'
ELSE 'On-time'
END AS "지연 여부"
FROM food_orders fo;
오늘의 TMI
그래도 아직까지는 SQL에 벽 안느껴서 다행이랄까... 막힐 때는 많아도 그게 엄청 힘들다거나 하지는 않아서 다행. 그냥 매번 다른 사람들 풀이 보고 감탄만 하는 중...