테이블?
CREATE DATABASE 데이터베이스명 -- 데이터베이스 생성하기
Ctrl + Shift + Entermember)에 마우스를 올려서 나타나는 두번째 아이콘을 클릭하면 column, datatype, pk, default 등의 정보가 나타남id라는 컬럼을 확인할 수 있음 ← member 테이블에서 회원을 식별하기 위해 인위적으로 추가한 식별자 컬럼 (Primary Key)임PK, NN(자동으로 체크됨, Not Null의 줄임말) 밑의 체크박스를 체크해서 명시적으로 식별자 컬럼으로 설정해주기-Null은 빈 문자열 ("")이나 0과는 다른 개념
PK를 설정할 때 AI 옵션의 체크박스를 체크하면, 이후에 사용자가 row를 삽입할 때 회원의 실제 속성을 나타내는 컬럼의 값만 직접 작성하고 id 컬럼에는 신경쓸 필요가 없도록 자동으로 +1씩 증가시켜서 중복을 방지해주는 속성birthday, sign_up_day 등의 날짜타입들은 자동으로 TEXT의 데이터타입을 부여받지만, 그보다는 DATE 타입이 더 적절함INT: 정수형DOUBLE: 실수형DATE: 날짜형TEXT: 문자열memeber 테이블 이름 위에 마우스를 올리고 가장 오른쪽의 아이콘을 누르면 멤버테이블 전체가 보임SELECT * FROM copang_main.member; -- 테이블의 데이터 조회
https://www.codeit.kr/topics/data-analysis-using-sql/lessons/3158
SELECT: 테이블의 데이터를 조회할 때 사용SELECT 컬럼(들) FROM 데이터베이스.테이블명; -- 테이블의 데이터 조회
데이터베이스.테이블명으로 기재하는 것이 번거롭다면, 아래와 같이 USE를 사용할 수도 있음USE coupang_main -- 데이터베이스명
SELECT 컬럼(들) FROM member; -- 테이블명
WHERE: 조건문SELECT email FROM coupang_main.member;
WHERE email = "minzikx@gmail.com";
SELECT * FROM coupang_main.member;
WHERE age >= 27;
BETWEEN (꼭 숫자가 아니어도 날짜 등에도 적용 가능)SELECT * FROM coupang_main.member;
WHERE age BETWEEN 30 AND 39;
NOTSELECT * FROM coupang_main.member;
WHERE age NOT BETWEEN 30 AND 39;
SELECT * FROM coupang_main.member;
WHERE sign_up_day > '2019-01-01';
SELECT * FROM coupang_main.member;
WHERE sign_up_day BETWEEN '2018-01-01' AND '2018-12-31';
SELECT * FROM coupang_main.member;
WHERE address LIKE '서울%'; -- 서울로 시작하는 모든 문자열
SELECT * FROM coupang_main.member;
WHERE address LIKE '%고양시%'; -- 고양시가 들어가는 모든 문자열
이스케이핑: 만약 100%와 같이 검색하고자 하는 문자열 안에 %가 들어간다면, LIKE 100\%처럼 % 앞에 역슬래쉬 \를 적어줘야 함
대소문자: 만약 yummy가 포함된 row들을 조회하되, 대문자가 아닌 오로지 소문자만으로 구성된 yummy만 포함하고 싶다면, LIKE BINARY '%yummy'라고 적어줘야 함
!=, <>SELECT * FROM coupang_main.member;
-- 두가지 방법
WHERE gender != 'm';
WHERE gender <> 'm'
INSELECT * FROM coupang_main.member;
WHERE age IN (20, 30);
_SELECT * FROM coupang_main.member;
WHERE email LIKE 'c______@%';
YEAR(), MONTH(), DAY()DATEDIFF(날짜1, 날짜2)DATEDIFF(’2018-01-05’, ’2018-01-03’)는 2CURDATE()DATE_ADD(), DATE_SUB()AND와 OR의 우선순위는 같고, 먼저 등장하는 것이 먼저 실행됨.
되도록 혼동을 피하기 위해 원하는 조건을 괄호로 묶는 것이 좋음
남자이면서 서울에 사는 회원 조회 - AND
SELECT * FROM coupang_main.member;
WHERE gender = 'm'
AND address LIKE '서울%'
AND age BETWEEN 25 and 29;
ORSELECT * FROM coupang_main.member;
WHERE MONTH(sign_up_day) BETWEEN 3 AND 5 -- 봄?
OR MONTH(sign_up_day) BETWEEN 9 AND 11; -- 가을?
SELECT * FROM coupang_main.member;
WHERE (gender = 'm' AND height >= 180) -- 남자 180 이상
OR (gender = 'f' AND height >= 170); -- 여자 170 이상
SELECT * FROM copang_main.member
ORDER BY height ASC; -- ASC는 생략 가능(디폴트이므로)
ASC는 오름차순, DESC는 내림차순SELECT * FROM copang_main.member
WHERE gender = 'm' -- 조건문으로 먼저 필터링 가능
AND weight >= 70
ORDER BY height ASC;
SELECT * FROM copang_main.member
ORDER BY YEAR(sign_up_day) DESC, age ASC;
data가 숫자인데 문자열 타입이라서 부정확한 정렬이 일어나고 있다면?CAST 사용CAST(data AS signed) ← signed : 양수와 음수를 포함한 모든 정수를 나타낼 수 있는 데이터 타입 (정수의 경우)decimal (소수의 경우)SELECT * FROM copang_main.member
ORDER BY YEAR(sign_up_day) DESC
LIMIT 10; -- 10개의 행만 추려서 출력하기
SELECT * FROM copang_main.member
ORDER BY YEAR(sign_up_day) DESC
LIMIT 8, 2; -- 8번째(포함), 9번째 이렇게 2개의 행 출력
FROM - WHERE - ORDER BY - LIMITCOUNTSELECT COUNT(email) FROM copang_main.member
SELECT COUNT(*) FROM copang_main.member
MAX : height 컬럼의 값 중 가장 큰 값(195.2) 출력하기SELECT MAX(height) FROM copang_main.member
MIN : weight 컬럼의 값 중 가장 작은 값 (48.2) 출력하기SELECT MIN(weight) FROM copang_main.member
AVG : weight 컬럼의 평균값 구하기SELECT AVG(weight) FROM copang_main.member -- 67.xxx
SELECT SUM(age) FROM copang_main.member;
SELECT STD(age) FROM copang_main.member;
SELECT CEIL(height) FROM copang_main.member;
FLOOR() 함수 - 내림 함수
ROUND() 함수 - 반올림 함수
ABS() 함수 - 절대값을 구하는 함수
SQRT() 함수 - 제곱근을 구하는 함수
SELECT * FROM copang_main.member
WHERE address IS NULL;
SELECT * FROM copang_main.member
WHERE address IS NULL
OR weight IS NULL
OR height IS NULL;
✨ 주의: IS NULL은 = NULL로 대체될 수 없음!! 즉, NULL과는 앞서 배운 비교기호들인 =, !=, <> 등을 모두 사용할 수 없음.
NULL을 다른 단어로 바꾸기 (대체하기)SELECT
COALESCE(height, '####')
-- height 컬럼의 null값은 '####'로 대체
COALESCE(weight, '---')
COALESCE(address, '@@@')
FROM copang_main.member;
NULL에는 어떤 연산을 해도 결국 자기자신임NULL + 5 = NULLSELECT AVG(age) FROM copang_main.member -- 평균 구하기
WHERE age BETWEEN 5 AND 100; -- 정상치만 추리기
SELECT * FROM copang_main.member -- 평균 구하기
WHERE adress NOT LIKE '%호'; -- 정상치만 추리기
SELECT email, height, weight, weight / ((height/100) * (height/100)) — bmi에서 키 단위가 미터이므로 센티 단위의 키를 100으로 나눠줘야 함
FROM copang_main.member;
+, -, *, /, % 등의 연산자 사용가능SELECT
email,
weight / ( (height/100) * (height/100)) AS BMI
FROM copang_main.member;
만약 두 열을 합치고 제목을 하나로 만들고 싶다면? Concat!!
SELECT
emaiL,
CONCAT (height, ' cm' weight, 'kg') AS '키와 몸무게',
weight / (height/100)) * (height/100)) AS BMI
FROM copang_main. member;
결과>
키와 공무게
165.7cm, 67.3kg
CASE
WHEN blahblah THEN blahblah
WHEN blahblah THEN blahblah
WHEN blahblah THEN blahblah
ELSE blahblah
SELECT name,
price,
price/cost,
(CASE
WHEN price/cost >= 1 AND price/cost < 1.5 THEN 'C. 저효율 메뉴'
WHEN price/cost >= 1.5 AND price/cost < 1.7 THEN 'B. 중효율 메뉴'
WHEN price/cost >= 1.7 THEN 'A. 고효율 메뉴'
END) AS efficiency
FROM pizza_price_cost
ORDER BY efficiency DESC, price ASC
LIMIT 6;
a < x < b 불가, a < x AND x < b로 풀어서 적어야 함DISTINCT : 컬럼값들의 중복을 제거해줌SELECT DISTINCT(gender) FROM copang_main.member;
DISTINCT를 이용해서 고유값을 뽑을 수 있을까?SELECT DISTINCT(SUBSTRING(address, 1, 2)) FROM copang_main.member;
SUBSTRING(대상컬럼, 시작인덱스(1부터), 끝인덱스) : 대상컬럼의 문자열을 시작인덱스부터 끝인덱스까지만 각각 출력하도록 함LENGTH() 함수: 문자열의 길이를 구해줍니다.UPPER() 함수: 문자열을 모두 대문자로 바꿔서 보여주는 함수LOWER() 함수: 문자열을 모두 소문자로 바꿔서 보여주는 함수LPAD(컬럼, 채울개수, 특정문자열) : LEFT(왼쪽) + PADDING(채우기)의 줄임말RPAD(컬럼, 채울개수, 특정문자열) : RIGHT(오른쪽) + PADDING(채우기)의 줄임말LTRIM() : 왼쪽 공백 삭제RTRIM() : 오른쪽 공백 삭제TRIM() : 왼쪽, 오른쪽 양쪽 다 공백 삭제SELECT gender, COUNT(*)
FROM copang_main.member
GROUP BY gender
이 때 count 함수는 전체에 적용되는 것이 아니라 GROUP BY 함수로 묶인 각 그룹에 적용됨
각 그룹의 row 개수가 출력됨
만약 count 함수 자리에 AVG(height) 를 넣어도 각 그룹 별 평균을 구하게 됨
동일하게 MIN 등도 사용가능
GROUP BY 이후에 SELECT 절에서 함수들을 사용하면 이제는 전체 컬럼에 대해 적용되는 것이 아니라 그룹별로 적용되게 됨!
SELECT
SUBSTRING(address, 1, 2) AS region,
COUNT(*) — 광역시 별 회원수 출력
FROM copang_main.member
GROUP BY SUBSTRING(address, 1, 2);
SELECT
SUBSTRING(address, 1, 2) AS region,
gender,
COUNT(*) — 광역시 별 회원수 출력
FROM copang_main.member
GROUP BY SUBSTRING(address, 1, 2),
gender;
그러면 이제
서울 | 남자
서울 | 여자
경기 | 남자
경기 | 여자
등으로 분류되게 됨!
SELECT
SUBSTRING(address, 1, 2) AS region,
gender,
COUNT(*) — 광역시 별 회원수 출력
FROM copang_main.member
GROUP BY SUBSTRING(address, 1, 2),
gender
HAVING region = ‘서울‘ — 조건문
AND gender = ‘m’ — 조건문 여러개 가능
SELECT
SUBSTRING(address, 1, 2) AS region,
gender,
COUNT(*) — 광역시 별 회원수 출력
FROM copang_main.member
GROUP BY SUBSTRING(address, 1, 2),
gender
HAVING region IS NOT NULL — region 컬럼의 null 값 제거
ORDER BY
region ASC,
gender DESC;
WITH ROLLUPSELECT SUBSTRING(address, 1, 2) as region,
gender,
COUNT(*)
FROM member
GROUP BY SUBSTRING(address, 1, 2), gender
WITH ROLLUP --
HAVING region IS NOT NULL
ORDER BY region ASC, gender DESC;
GROUP BY 컬럼을 기준으로 전체 합을 출력해줌 
WITH ROLLUP은 GROUP BY 뒤에 나오는 그루핑 기준의 등장 순서에 맞춰서 계층적인 부분 총계를 보여줌GROUP BY 뒤에 나오는 그루핑 기준의 등장 순서에 따라 WITH ROLLUP이 출력하는 결과가 달라짐 (제일 앞에 나오는 컬럼에 따라서 부분총계를 출력함)GROUPING() : NULL을 보았을 때 원래 있던 NULL인지, 부분 총계임을 나타내기 위해 쓰인 NULL인 건지를 구분하기 위해서 사용함 → 부분총계를 나타내기 위해 NULL이 쓰인 곳에는 1이 출력됨LEFT OUTER JOIN : 왼쪽 테이블을 기준으로 합쳐짐RIGHT OUTER JOIN : 오른쪽 테이블을 기준으로 합쳐짐SELECT
item.id,
item.name,
stock.item_id,
stock.inventory_count
FROM item LEFT OUTER JOIN stock -- 병합 방식
ON item.id = stock.item_id; -- 병합 기준
SELECT
i.id,
i.name,
s.item_id,
s.inventory_count
FROM item AS i LEFT OUTER JOIN stock AS s -- 병합 방식
ON item.id = stock.item_id; -- 병합 기준
INNER JOIN: 기준이 되는 테이블이 따로 없이, 두 테이블 전부에서 값이 있는 경우 (not null)에만 나타남 → 교집합!SELECT
item.id,
item.name,
stock.item_id,
stock.inventory_count
FROM item INNER JOIN stock -- 병합 방식
ON item.id = stock.item_id; -- 병합 기준
SELECT p.name,
COALESCE(s.sales_volume, '판매량 정보 없음') AS '판매량'
FROM pizza_price_cost AS p LEFT OUTER JOIN sales AS s ON p.id = s.menu_id;


INTERSECTMINUS, EXCEPTUNIONON : ON old.id = new.idUSING : USING(id) ← 두 테이블에서 조인 조건으로 사용되는 컬럼들의 이름이 같은 경우 사용 가능!SELECT id, nation, count FROM t1
UNION
SELECT id, nation, count FROM t2
이 때 t1과 t2의 나머지 컬럼들은 일치하지 않아도 괜찮음
UNION은 중복을 제거하고 정렬한 결과를 반환함, UNION ALL은 중복을 포함한 결과를 반환함

https://www.codeit.kr/topics/data-analysis-using-sql/lessons/3226
-- 남녀 공용 상품의 등록 연도별 평균 별점
SELECT YEAR(i.registration_date) AS '등록 연도',
COUNT(*) AS '리뷰 개수',
AVG(star) AS '별점 평균값'
FROM review AS r INNER JOIN item AS i ON r.item_id = i.id
INNER JOIN member AS m ON r.mem_id = m.id
WHERE i.gender = 'u'
GROUP BY YEAR(i.registration_date)
HAVING COUNT(*) >= 10
ORDER BY AVG(star) DESC;
SELECT i.id, i.name, AVG(star) AS avg_star
FROM item AS i LEFT OUTER JOIN review AS r
ON r.item_id = i.id
GROUP BY i.id, i.name
-- 별점평균이 전체 평균보다 작은 경우만 필터링하려면?
-- 전체평균을 구하는 식을 서브쿼리로 작성해서 조건문에 넣어주면 됨
HAVING avg_star < (SELECT AVG(star) FROM review)
ORDER BY avg_star DESC;
SELECT id, name, price,
(SELECT AVG(price) FROM item) AS avg_price
FROM table.item
SELECT * FROM item
WHERE id IN -- IN: 괄호 안의 하나라도 조건믈 만족하면 만족
( -- review 수가 3개 이상인 모든 상품의 id들을 반환
SELECT item_id
FROM review
GROUP BY item_id HAVING COUNT(*) >= 3
);