본격적인 시작에 앞서
1차시부터 너무 많은 분들이 제 글을 읽어주셔서 놀랐습니다... 8기에는 혼공박사와 석사에 두 번 정도 제 이름에 올라갔고, 특히나 1차시에 혼공 박사가 되었는데 이번에도 그 영광(?)을 얻을 수 있을지 조금 기대하겠습니다...
SELECT ~ FROM ~ WHERE
https://www.hanbit.co.kr/support/supplement_survey.html?pcode=B6846155853
여기서 예제 파일을 다운로드했습니다
DROP DATABASE IF EXISTS market_db; -- 만약 market_db가 존재하면 우선 삭제한다.
CREATE DATABASE market_db;
USE market_db;
CREATE TABLE member -- 회원 테이블
( mem_id CHAR(8) NOT NULL PRIMARY KEY, -- 사용자 아이디(PK)
mem_name VARCHAR(10) NOT NULL, -- 이름
mem_number INT NOT NULL, -- 인원수
addr CHAR(2) NOT NULL, -- 지역(경기,서울,경남 식으로 2글자만입력)
phone1 CHAR(3), -- 연락처의 국번(02, 031, 055 등)
phone2 CHAR(8), -- 연락처의 나머지 전화번호(하이픈제외)
height SMALLINT, -- 평균 키
debut_date DATE -- 데뷔 일자
);
CREATE TABLE buy -- 구매 테이블
( num INT AUTO_INCREMENT NOT NULL PRIMARY KEY, -- 순번(PK)
mem_id CHAR(8) NOT NULL, -- 아이디(FK)
prod_name CHAR(6) NOT NULL, -- 제품이름
group_name CHAR(4) , -- 분류
price INT NOT NULL, -- 가격
amount SMALLINT NOT NULL, -- 수량
FOREIGN KEY (mem_id) REFERENCES member(mem_id)
);
INSERT INTO member VALUES('TWC', '트와이스', 9, '서울', '02', '11111111', 167, '2015.10.19');
INSERT INTO member VALUES('BLK', '블랙핑크', 4, '경남', '055', '22222222', 163, '2016.08.08');
INSERT INTO member VALUES('WMN', '여자친구', 6, '경기', '031', '33333333', 166, '2015.01.15');
INSERT INTO member VALUES('OMY', '오마이걸', 7, '서울', NULL, NULL, 160, '2015.04.21');
INSERT INTO member VALUES('GRL', '소녀시대', 8, '서울', '02', '44444444', 168, '2007.08.02');
INSERT INTO member VALUES('ITZ', '잇지', 5, '경남', NULL, NULL, 167, '2019.02.12');
INSERT INTO member VALUES('RED', '레드벨벳', 4, '경북', '054', '55555555', 161, '2014.08.01');
INSERT INTO member VALUES('APN', '에이핑크', 6, '경기', '031', '77777777', 164, '2011.02.10');
INSERT INTO member VALUES('SPC', '우주소녀', 13, '서울', '02', '88888888', 162, '2016.02.25');
INSERT INTO member VALUES('MMU', '마마무', 4, '전남', '061', '99999999', 165, '2014.06.19');
INSERT INTO buy VALUES(NULL, 'BLK', '지갑', NULL, 30, 2);
INSERT INTO buy VALUES(NULL, 'BLK', '맥북프로', '디지털', 1000, 1);
INSERT INTO buy VALUES(NULL, 'APN', '아이폰', '디지털', 200, 1);
INSERT INTO buy VALUES(NULL, 'MMU', '아이폰', '디지털', 200, 5);
INSERT INTO buy VALUES(NULL, 'BLK', '청바지', '패션', 50, 3);
INSERT INTO buy VALUES(NULL, 'MMU', '에어팟', '디지털', 80, 10);
INSERT INTO buy VALUES(NULL, 'GRL', '혼공SQL', '서적', 15, 5);
INSERT INTO buy VALUES(NULL, 'APN', '혼공SQL', '서적', 15, 2);
INSERT INTO buy VALUES(NULL, 'APN', '청바지', '패션', 50, 1);
INSERT INTO buy VALUES(NULL, 'MMU', '지갑', NULL, 30, 1);
INSERT INTO buy VALUES(NULL, 'APN', '혼공SQL', '서적', 15, 1);
INSERT INTO buy VALUES(NULL, 'MMU', '지갑', NULL, 30, 4);
SELECT * FROM member;
SELECT * FROM buy;
예제 파일에 있는 코드입니다 처음부터 차근차근 살펴보겠습니다
DROP DATABASE IF EXISTS market_db; -- 데이터베이스를 삭제한다 / market_db가 존재한다면
CREATE DATABASE market_db; --market_db를 만든다
DROP문을 통해 데이터 베이스를 삭제할 수 있습니다.
IF문을 통해 DROP 할 조건을 제시하고, EXISTS는 데이터베이스가 존재하는지 나타냅니다
CREATE문을 통해 DATABASE를 생성했습니다.
USE market_db; -- market_db 선택 (앞으로 이 DB에서 진행한다)
CREATE TABLE member -- 회원 테이블
( mem_id CHAR(8) NOT NULL PRIMARY KEY, -- 사용자 아이디(PK)
mem_name VARCHAR(10) NOT NULL, -- 이름
mem_number INT NOT NULL, -- 인원수
addr CHAR(2) NOT NULL, -- 지역(경기,서울,경남 식으로 2글자만입력)
phone1 CHAR(3), -- 연락처의 국번(02, 031, 055 등)
phone2 CHAR(8), -- 연락처의 나머지 전화번호(하이픈제외)
height SMALLINT, -- 평균 키
debut_date DATE -- 데뷔 일자
);
CREATE TABLE buy -- 구매 테이블
( num INT AUTO_INCREMENT NOT NULL PRIMARY KEY, -- 순번(PK)
mem_id CHAR(8) NOT NULL, -- 아이디(FK)
prod_name CHAR(6) NOT NULL, -- 제품이름
group_name CHAR(4) , -- 분류
price INT NOT NULL, -- 가격
amount SMALLINT NOT NULL, -- 수량
FOREIGN KEY (mem_id) REFERENCES member(mem_id)
);
USE 문을 통해 market_db데이터베이스를 선택했습니다. USE문을 사용하지 않으면
`market_db`.`member` 이런 식으로 작성해야 하기 때문에 번거롭습니다.
CREATE문으로 member와 buy TABLE을 생성하였습니다.
INSERT INTO member VALUES('TWC', '트와이스', 9, '서울', '02', '11111111', 167, '2015.10.19');
INSERT INTO member VALUES('BLK', '블랙핑크', 4, '경남', '055', '22222222', 163, '2016.08.08');
INSERT INTO member VALUES('WMN', '여자친구', 6, '경기', '031', '33333333', 166, '2015.01.15');
INSERT INTO member VALUES('OMY', '오마이걸', 7, '서울', NULL, NULL, 160, '2015.04.21');
INSERT INTO member VALUES('GRL', '소녀시대', 8, '서울', '02', '44444444', 168, '2007.08.02');
INSERT INTO member VALUES('ITZ', '잇지', 5, '경남', NULL, NULL, 167, '2019.02.12');
INSERT INTO member VALUES('RED', '레드벨벳', 4, '경북', '054', '55555555', 161, '2014.08.01');
INSERT INTO member VALUES('APN', '에이핑크', 6, '경기', '031', '77777777', 164, '2011.02.10');
INSERT INTO member VALUES('SPC', '우주소녀', 13, '서울', '02', '88888888', 162, '2016.02.25');
INSERT INTO member VALUES('MMU', '마마무', 4, '전남', '061', '99999999', 165, '2014.06.19');
INSERT INTO buy VALUES(NULL, 'BLK', '지갑', NULL, 30, 2);
INSERT INTO buy VALUES(NULL, 'BLK', '맥북프로', '디지털', 1000, 1);
INSERT INTO buy VALUES(NULL, 'APN', '아이폰', '디지털', 200, 1);
INSERT INTO buy VALUES(NULL, 'MMU', '아이폰', '디지털', 200, 5);
INSERT INTO buy VALUES(NULL, 'BLK', '청바지', '패션', 50, 3);
INSERT INTO buy VALUES(NULL, 'MMU', '에어팟', '디지털', 80, 10);
INSERT INTO buy VALUES(NULL, 'GRL', '혼공SQL', '서적', 15, 5);
INSERT INTO buy VALUES(NULL, 'APN', '혼공SQL', '서적', 15, 2);
INSERT INTO buy VALUES(NULL, 'APN', '청바지', '패션', 50, 1);
INSERT INTO buy VALUES(NULL, 'MMU', '지갑', NULL, 30, 1);
INSERT INTO buy VALUES(NULL, 'APN', '혼공SQL', '서적', 15, 1);
INSERT INTO buy VALUES(NULL, 'MMU', '지갑', NULL, 30, 4);
INSERT문으로 테이블에 값을 넣었습니다. INT형은 따옴표 없이, VARCHAR와 CHAR는 작은따옴표로 묶어 표현합니다.
** SELECT 문**
SELECT slect_expr -- 열 이름
[FROM table_reference] -- 테이블 이름
[WHERE where_condition] -- 조건식
[GROUP BY {col_name | expr | position }] -- 열 이름
[HAVING where_condidion] -- 조건식
[ORDER BY {col_name { expr | position}] -- 열 이름
[LIMIT {[offset,] row_count | rouw_count OFFSET offset}] -- 개수 제한
SELECT는
이 버튼을 눌렀을 때(execute) 가져올 열을 의미합니다.
* 은 테이블의 모든 열을 가져온다는 의미입니다.
FROM~ 은 SELECT로 가져올 열이 속한 테이블을 선택합니다.
ex)
SELECT * FROM member; -- member 테이블의 모든 열 가져오기
SELECT addr, debut_datee FROM member; -- member 테이블의 addr, debut_date 열 가져오기
WHERE문
WHERE 절은 조회하는 결과에 특정한 조건을 추가해서 조건에 해당하는 데이터를 가져옵니다.
SELECT 열 이름
FROM 테이블 이름
WHERE 조건 ;
ex)
SELECT * FROM WHERE mem_number = 4;
WHERE 절의 조건에 해당하는 데이터만 불러왔습니다
WHERE 절에는 관계 연산자와 논리 연산자도 사용할 수 있습니다.
SELECT *
FROM member
WHERE height >= 163 AND height <= 165;
위처럼 WHERE 절이 특정한 값의 범위를 나타내는 경우에는
WHERE height BETWEEN 163 AND 165;
BETWEEN a AND b로 쓸 수 있습니다
SELECT mem_name, addr
FROM market_db.member
WHERE addr = '경기' OR addr = '전남' OR addr = '경남'
;
addr이 경기, 전남, 경남인 데이터를 찾고 싶을 때에는 OR문으로도 쓸 수 있지만
IN()을 사용하여 작성할 수 있습니다.
문자열의 일부 문자를 검색하려면 LIKE를 사용합니다
SELECT *
FROM market_db.member
WHERE mem_name LIKE '우%'--제일 앞 글자가 우 인 모든 데이터
;
'%우%' --우가 들어가는 모든 데이터
'%우' --우로 끝나는 모든 데이터
교재에는 언급되어 있지 않지만 추가적으로 알아두시면 좋을 거 같습니다!
한 글자와 매치하기 위해서는 언더바를 사용합니다.
SELECT *
FROM market_db.member
WHERE mem_name LIKE '__핑크' -- 앞 두 글자는 상관 없고, 핑크로 끝나는 데이터
;
+) 서브쿼리
에이핑크 회원의 평균 키 보다 큰 회원을 구하고자 합니다
SELECT height
FROM market_db.member
WHERE mem_name ='에이핑크';
이 코드로 에이핑크 회원의 키는 164인 것을 알 수 있습니다.
SELECT mem_name
FROM market_db.member
WHERE height > 164;
;
이처럼 에이핑크 회원의 평균 키 보다 큰 회원을 조회하려면 두 개의 쿼리가 필요합니다.
SELECT mem_name
FROM market_db.member
WHERE height > (SELECT height FROM market_db.member WHERE mem_name ='에이핑크');
-- 괄호 안의 값은 164
위의 두 쿼리를 하나로 합쳤습니다. 아래처럼 하나의 SELECT 문에 다른 SELECT가 들어갈 수 있고, 이것을 서브쿼리라고 합니다. 서브쿼리는 2개의 SQL문을 하나로 만들어 하나의 SQL만 관리하면 되기 때문에 더 간단해집니다. 서브쿼리는 실무에서도 자주 사용된다고 하네요.
2. SELECT문 심화
** ORDER BY**
ORDER BY 절은 결과의 값이나 개수에 대해서는 영향을 미치지 않지만, 결과가 출력되는 순서를 조절합니다.
SELECT mem_id, mem_name, debut_date
FROM member
ORDER BY debut_date;
위와 같이 입력하여 실행하면 데뷔 일자가 빠른 순서대로 출력됩니다.
ORDER BY의 기본값은 오름차순이지만 ASC와 DESC로 오름차순 또는 내림차순으로 정렬할 수 있습니다
- ASC(Ascending) : 오름차순
- DESC(Descending) : 내림차순
ex)
SELECT mem_id, mem_name, debut_date
FROM member
ORDER BY debut_date DESC;
WHERE절과 ORDER BY절을 함께 쓸 수 있습니다. 하지만 이때 ORDER BY 절은 WHERE절 다음에 작성해야 합니다.
ex)
SELECT *
FROM member
WHERE height >= 164
ORDER BY height DESC;
여러 개의 정렬 기준을 지정할 수 있습니다.
ex)
SELECT *
FROM member
ORDER BY height DESC, dabut_date ASC;
이 쿼리는 평균키를 큰 순서대로 정렬하되, 평균 키가 같으면 데뷔 일자가 빠른 순서로 정렬하도록 합니다.
** LIMIT**
LIMIT은 출력하는 개수를 제한합니다.
SELECT *
FROM mamber
LIMIT 5; -- 5개만 출력
LIMIT의 형식은 LIMIR 시작, 개수입니다. 위의 코드처럼 작성 시 LIMIT 0, 5과 같습니다.
ex)
SELECT *
FROM member
ORDER BY height DESC -- 키가 큰 순서대로
LIMIT 3, 2; -- 3번째부터 2번째
** DISTINCT**
DISTINCT는 조회된 결과에서 중복된 데이터를 1개만 남깁니다.
SELECT addr FROM member;
중복된 값이 그대로 출력됩니다.
SELECT DISTINCT addr
FROM member;
중복된 값이 걸러져서 나옵니다.
(5) GROUP BY
GROUP BY 절은 말 그대로 데이터를 그룹으로 묶어주는 역할을 합니다.
GROUP BY와 함께 쓰이는 집계 함수들에 대해 알아보도록 하겠습니다.
- SUM() : 합계를 구합니다.
- AVG() : 평균을 구합니다.
- MIN() : 최솟값을 구합니다.
- MAX() : 최댓값을 구합니다.
- COUNT() : 행의 개수를 셉니다.
- COUNT(DISTINCT) : 행의 개수를 셉니다. (중복은 1개만 인정)
같은 회원의 총 구매 개수를 구해보도록 하겠습니다.
SELECT mem_id "회원 아이디", SUM(amount) "총 구매 개수" -- " " 로 묶은 것들은 별칭입니다.
FROM buy GROUP BY mem_id;
HAVING
HAVING절은 WHERE과 같이 출력할 데이터의 조건을 제한합니다. 하지만 WHERE절은 집계 함수에 사용할 수 없기 때문에 집계함수가 쓰였을 때 HAVING을 사용합니다. HAVING은 GROUP BY 절 뒤에 나와야 합니다.
ex)
SELECT mem_id "회원 아이디", SUM(price*amount) "총 구매 금액"
FROM market_db.buy
GROUP BY mem_id
HAVING SUM(price*amount) > 1000
;
* 기본 미션 : 138p 2번 문제 풀고 인증하기
Q. 다음 보기 중에서 각 문항의 빈칸에 들어갈 것을 고르세요.
LIKE, DESC, ORDER BY, DISTINCT, ASC, AND, OR, >=, LIMIT
- SELECT * FROM member ( ) height;
- SELECT * FROM member ( ) 5, 2;
- SELECT ( ) phone1 FROM member;
답은 순서대로 ORDER BY, LIMIT, DISTINCT 입니다.
height의 값이 작은 순서대로 정렬합니다.
member에서 5번째에서 2번째의 항목을 출력합니다.
phone1의 중복되는 항목 중 하나만 출력합니다.
** 데이터 변경을 위한 SQL 문**
SELECT문과 이번에 보게 될 INSERT, DELETE, UPDATE 문은 DMS(data Mainpulation language)에 속합니다.
DMS의 개념은 이번 챕터에서 소개되지 않지만 간단하게 설명하자면 말 그대로 데이터 조작 언어로, 데이터 베이스의 검색, 등록, 삭제, 갱신을 할 수 있는 언어입니다.
** INSERT +선택미션**
INSERT는 테이블에 행 데이터를 입력하는 기본적인 SQL문입니다.
INSERT 문의 형식은 다음과 같습니다.
INSERT INTO 테이블 (열1, 열2, ... ) VALUES (값1, 값2, ... )
-- 열은 생략 가능, VALUES 의 순서 및 개수는 테이블을 정의할 때의 열 순서 및 개수와 동일해야 함
USE market_db;
CREATE TABLE hongong1 (toy_id INT, toy_name CHAR(4), age INT);
INSERT INTO hongong1 VALUES (1, '우디', 25);
SELECT * FROM hongong1;
hongong1 테이블을 만든 뒤, 각 열에 1, '우디', 25 값을 입력했습니다
테이블에 값이 들어간 것을 확인할 수 있습니다.
AUTO_INCREMENT
AUTO_INCREMENT는 1부터 증가하는 값을 자동으로 입력해 줍니다. 해당 열은 PRIMARY KEY로 지정해야 합니다.
USE market_db;
CREATE TABLE hongong2 (
toy_id INT AUTO_INCREMENT PRIMARY KEY,
toy_name CHAR(4),
age INT
);
toy_id를 AUTO_INCREMENT로 지정한 테이블입니다
INSERT INTO hongong2 VALUES (NULL, '보핍', 25);
INSERT INTO hongong2 VALUES (NULL, '슬링키', 22);
INSERT INTO hongong2 VALUES (NULL, '렉스', 21);
SELECT * FROM hongong2;
toy_id를 NULL로 두었지만, 자동으로 숫자가 입력됩니다.
SELECT LAST_INSERT_ID();
위 코드를 통해 어느 숫자까지 증가했는지 확인할 수 있습니다.
ALTER TABLE hongong2 AUTO_INCREMENT=100;
INSERT INTO hongong2 VALUES (NULL, '재남', 35);
SELECT * FROM hongong2;
만약 자동으로 입력되는 값을 100부터 설정하시고 싶다면 ALTER TABLE을 통해 AUTO_INCREMENT를 변경할 수 있습니다.
INSERT INTO ~ SELECT
INSERT INTO ~ SELECT 구문은 다른 테이블의 데이터를 가져와 한 번에 대량으로 입력할 수 있습니다.
형식은 다음과 같습니다.
INSERT INTO 테이블_이름 (열_이름1, 열_이름2, ... )
SELECT 문;
이때 SELECT문의 열 개수는 INSERT 할 테이블의 열 개수와 같아야 합니다.
CREATE TABLE city_popul (city_name CHAR(35), population INT);
city_popul 테이블을 만들었습니다.
INSERT INTO city_popul
SELECT Name, Population FROM world.city;
city_popul에 원래 있던 world의 city 테이블 값을 입력했습니다.
위 코드를 입력하면 다음과 같은 메시지가 나오고, 값이 입력됩니다.
** UPDATE**
UPDATE는 기존에 입력되어 있는 값을 수정하는 명령입니다. 기본적인 형식은 다음과 같습니다.
UPDATE 테이블_이름
SET 열1=값1, 열2=값2, ...
WHERE 조건;
ex)
UPDATE city_popul
SET city_name='서울'
WHERE city_name='Seoul';
SELECT * FROM city_popul WHERE city_name='서울';
UPDATE문을 통해 city_name이 Seoul인 것을 서울로 바꿨습니다.
UPDATE문에 WHERE 절을 사용하지 않으면 모든 행의 데이터가 변경됩니다. 모든 행의 데이터를 바꾸고 싶을 때에는 WHERE 절 없이 사용할 수 있습니다.
DELETE +선택미션
DELETE는 행 단위로 삭제하며 WHERE가 없으면 전체 행이 삭제됩니다.
형식은 다음과 같습니다.
DELETE FROM 테이블이름 WHERE 조건;
ex)
DELETE FROM city_popul
WHERE city_name LIKE 'New%';
New로 시작하는 city_name을 삭제하였습니다.
마무리
확실히 1주 차보다 더 많은 내용이 담겨있습니다. 교재에서도 두 번 보는 것을 추천하고 있네요.
다음 챕터인 SQL고급 문법을 숙지하기 위해서는 철저하게 공부하는 것이 좋을 거 같습니다.
제 글 읽어주셔서 감사합니다.
'DB > MySQL' 카테고리의 다른 글
[MySQL] 스토어드 프로시저와 SQL의 파이썬 연결 (0) | 2023.02.14 |
---|---|
[MySQL] 인덱스란 무엇일까? (0) | 2023.02.06 |
[MySQL] 테이블과 뷰 (0) | 2023.01.30 |
[MySQL] SQL 고급 문법 (0) | 2023.01.16 |
[혼공S] 데이터 베이스와 SQL (0) | 2022.12.29 |