SELECT는 테이블에서 데이터를 조회하는 기능을 한다. SELECT의 가장 기본 형식은 SELECT ~ FROM ~ WHERE로 SELECT 다음에는 열 이름, FROM 다음에는 테이블 이름, WHERE 다음에는 조건식이 나온다. WHERE 다음에 나오는 조건식에 따라 원하는 데이터를 추출 및 필터링할 수 있다.

해당 DB는 인터넷 마켓 DB 구성도이다. 앞으로 해당 테이블을 기반으로 데이터를 조회 및 조작해보도록 하겠다.
여기서 FK는 Foreign Key로 현재로써는 member 테이블의 ID와 buy 테이블의 아이디를 이어주는 개념으로 생각하면 된다.
테이블 간의 관계는 사용자가 인터넷 마켓에 가입을 하여 정보(아이디, 이름, 인원, 주소, 국번, 전화번호, 평균 키, 데뷔 일자)를 입력하여 회원가입한 후, 마켓의 상품을 구매하면 buy 테이블에 물건을 구매한 아이디와 물품명, 분류와 단가, 주문 수량을 저장할 예정이다.
데이터베이스 생성은 CREATE DATABASE (데이터베이스명);으로 생성할 수 있다.
CREATE DATABASE market_db;
위 문장을 실행하여 market_db라는 데이터베이스를 생성하였다.
데이터베이스 삭제는 DROP DATABASE (데이터베이스명);으로 삭제할 수 있다.
DROP DATABASE market_db;
DROP DATABASE IF EXISTS market_db;
이때 IF EXISTS라는 명령문을 추가로 붙일 경우, market_db가 존재한다면 삭제하는것으로 실행된다.
데이터베이스를 생성하고, 해당 데이터베이스에 테이블을 생성하려면 데이터베이스를 선택해야한다.
데이터베이스 선택은 USE (데이터베이스명);으로 선택할 수 있다.
USE market_db;
위 문장을 실행하여 market_db를 선택하였다.
주석을 통해 내가 쓴 코드의 설명을 쓸 수 있는데, SQL에서 주석은 하이픈(-) 2개를 연속으로 쓰고 작성한다.
이때, 하이픈 2개를 쓴 후 한 칸을 띄우고 설명을 작성한다.
USE market_db;-- 주석입니다.
이처럼 —- 주석입니다. 라고 작성 시, 설명에는 보이지만 실제 쿼리 실행에는 반영되지 않는다.
테이블 생성은 CREATE TABLE (테이블명) (컬럼 정의1. 컬럼 정의2…);로 생성할 수 있다.
CREATE TABLE member
(
mem_id CHAR(8) NOT NULL PRIMARY KEY,
mem_name VARCHAR(10) NOT NULL,
mem_number INT NOT NULL,
addr CHAR(2) NOT NULL,
phone1 CHAR(3),
phone2 CHAR(8),
height SMALLINT,
debut_date DATE
);
위 명령을 실행하여 member 테이블을 생성하였다.
여기서 VARCHAR은 CHAR과 동일하게 문자를 저장하나 차이가 있다. 해당 차이점은 후에 살펴보도록 하겠다.
CREATE TABLE buy
(
num INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
mem_id CHAR(8) NOT NULL,
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)
);
마찬가지로 buy 테이블을 생성하였다. 해당 테이블에는 AUTO_INCREMENT라는 속성이 나오는데, 일단 자동으로 숫자가 증가되어 저장된다고 생각하자.
데이터 입력은 INSERT INTO 테이블명 (컬럼명, 생략 가능) VALUES(데이터);와 같은 형식으로 데이터를 삽입할 수 있다.
INSERT INTO member VALUES('TWC', '트와이스', 9, '서울', '02', '11111111', 167, '2015.10.19');
CHAR, VARCHAR, DATE형은 작은 따옴표로 감싸고, INT형은 작은 따옴표없이 값을 적어주면 된다.
INSERT INTO buy VALUES(NULL, 'BLK', '지갑', NULL, 30, 2);
또한 buy 테이블의 순번에 해당하는 num은 AUTO_INCREMENT로 설정하였으므로 NULL로 써줘도 자동으로 숫자가 증가되어 입력된다. 이 쿼리문으로 첫 데이터가 삽입되므로 1이 num 값에 저장된다.
데이터 조회는 SELECT (* 또는 컬럼명) FROM 테이블명;과 같은 형식으로 조회할 수 있다.
SELECT * FROM member;
SELECT * FROM buy;
해당 쿼리는 구축이 완료된 테이블에서 데이터를 추출하는 기능을 하며 기존의 데이터 변경하지 않는다.
가장 기본 형식은 SELECT (열 이름) FROM (테이블명) WHERE (조건식)의 형태로 조건식을 다양하게 표현하여 데이터베이스에서 원하는 데이터 추출 가능
(열 이름)란에 *를 사용할 경우, (테이블명)에 해당하는 테이블의 모든 열을 조회할 수 있다.
SELECT select_expr
[FROM table_references]
[WHERE where_condition]
[GROUP BY {col_name | expr | position}]
[HAVING where_condition]
[ORDER BY {col_name | expr | position}]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
SELECT 열 이름
FROM 테이블 이름
WHERE 조건식
GROUP BY 열 이름
HAVING 조건식
ORDER BY 열 이름
LIMIT 숫자
SELECT문의 전체적인 형태로, 대괄호로 묶인 부분은 생략 가능하다.
우선 데이터를 조회하기 위해 아래 2개의 쿼리문을 실행시키자.
INSERT INTO member VALUES ('APN', '에이핑크', 6, '경기', '031', '77777777', 164, '2011.02.10'),
('BLK', '블랙핑크', 4, '경남', '055', '22222222', 163, '2016.08.08'),
('GRL', '소녀시대', 8, '서울', '02', '44444444', 168, '2007.08.02'),
('ITZ', '잇지', 5, '경남', NULL, NULL, 167, '2019.02.12'),
('MMU', '마마무', 4, '전남', '061', '99999999', 165, '2014.06.19'),
('OMY', '오마이걸', 7, '서울', NULL, NULL, 160, '2015.04.21'),
('RED', '레드벨벳', 4, '경북', '054', '55555555', 161, '2014.08.01'),
('SPC', '우주소녀', 13, '서울', '02', '88888888', 162, '2016.02.25'),
('TWC', '트와이스', 9, '서울', '02', '11111111', 167, '2015.10.19'),
('WMN', '여자친구', 6, '경기', '031', '33333333', 166, '2015.01.15');
INSERT INTO buy VALUES (NULL, 'BLK', '지갑', NULL, 30, 2),
(NULL, 'BLK', '맥북프로', '디지털', 1000, 1),
(NULL, 'APN', '아이폰', '디지털', 200, 1),
(NULL, 'MMU', '아이폰', '디지털', 200, 5),
(NULL, 'BLK', '청바지', '패션', 50, 3),
(NULL, 'MMU', '에어팟', '디지털', 80, 10),
(NULL, 'GRL', '책', '서적', 15, 5),
(NULL, 'APN', '책', '서적', 15, 2),
(NULL, 'APN', '청바지', '패션', 50, 1),
(NULL, 'MMU', '지갑', NULL, 30, 1),
(NULL, 'APN', '책', '서적', 15, 1),
(NULL, 'MMU', '지갑', NULL, 302, 4);
이제 market_db에 존재하는 member 테이블과 buy 테이블에 데이터가 모두 입력되었으니 데이터를 조회해보자.
<실행>
SELECT * FROM member;
<결과>

쿼리를 입력한 결과 member 테이블의 모든 데이터가 조회되었다. 앞서 말했듯이, SELECT는 테이블에서 데이터를 조회할 때 사용하는 예약어로, SELECT 다음에 컬럼명이 아닌 *을 사용할 경우 FROM 뒤에 나오는 테이블에 존재하는 모든 열을 가져온다.
SELECT * FROM market_db.member;
원래 테이블의 전체 이름은 (데이터베이스명).(테이블명) 형식으로 작성하는 것이 원칙이나 USE문을 사용하여 데이터베이스 자동 선택되었기에 우리는 (데이터베이스명)을 입력할 필요가 없다.
이번에는 member 테이블에서 전체 열이 아닌, 이름(mem_name)만 조회해보도록 하겠다.
<실행>
SELECT mem_name FROM member;
<결과>

쿼리 실행 결과, Jmember 테이블의 mem_name 열만 추출된 것을 확인할 수 있다.
여러 개의 열을 가지고 싶을 때는 컬럼명을 ,로 구분하면 되고 테이블을 만들 때 컬럼의 순서와 상관 없이 데이터 출력 시 원하는 순서로 컬럼명을 입력하면 된다.
<실행>
SELECT addr, debut_date, mem_name FROM member;
<결과>

member 테이블의 addr, debut_date, mem_name의 순서로 열을 추출하기 위해 SELECT 다음에 컬럼명을 입력하였고, 성공적으로 데이터를 조회할 수 있었다.
작은 양의 데이터라면 전체 데이터에서 원하는 데이터를 찾는건 쉽지만, 데이터가 1만 건, 10만 건… 등 높은 단위로 올라가면 전체 데이터에서 원하는 데이터를 찾기란 쉽지 않다.
이럴 때는 WHERE에 조회하고 싶은 데이터가 가진 특징을 조건으로 걸어서 조회할 수 있다.
SELECT 열 이름 FROM 테이블 이름 WHERE 조건식;
SELECT 열 이름
FROM 테이블 이름
WHERE 조건식;
WHERE절은 조회하는 결과에 특정한 조건을 추가해서 원하는 데이터만 조회하는 것이다.
두 가지 형태의 SELECT~FROM~WHERE~가 있는데 여러 줄에 쓰는 형식은 세미콜론이 나오기 전까지 한 줄로 쓰는 것과 동일한 것으로 취급한다.
이번에는 member 테이블에서 이름이 ‘블랙핑크’인 member를 찾아보자.
<실행>
SELECT * FROM member WHERE mem_name = '블랙핑크';
<결과>

mem_name이 블랙핑크인 데이터를 추출하기 위해 WHERE mem_name = ‘블랙핑크’라는 조건을 추가하였다. 이때 mem_name은 문자형(CHAR)이므로 작은 따옴표로 묶어야한다.
=는 관계 연산자로 두 값이 동일할 때 true값을 가지며, WHERE는 뒤에 나오는 조건들의 결과가 참이되는 데이터만 추출한다.
<실행>
SELECT * FROM member WHERE mem_number = 4;
<결과>

이번에는 mem_number가 4인 데이터를 조회하였다. mem_number는 숫자형이므로 작은 따옴표 필요없다. 조회 결과, 블랙핑크와 마마무, 레드벨벳이 mem_number가 4이므로 모두 조회된 것을 확인할 수 있다.
이번에는 member 테이블의 데이터 중에서, 평균 키(height)가 162 이하인 멤버들의 아이디(mem_id)와 이름(mem_name)을 조회해보도록 하자.
<실행>
SELECT mem_id, mem_name FROM member WHERE height <= 162;
<결과>

height가 162 이하인 데이터를 추출하기 위해 관계 연산자 <=를 사용하여 조회하였다. 관계 연산자의 종류는 아래와 같다.
| 관계 연산자 | 사용 예 | 의미 |
|---|---|---|
| > | column value>value | column value가 value보다 클 시 true |
| < | column value<value | column value가 value보다 작을 시 true |
| >= | column value>=value | column value가 value보다 크거나 같을 시 true |
| <= | column value<=value | column value가 value보다 작거나 같을 시 true |
| = | column value=value | column value가 value와 같을 시 true |
| != | column value!=value | column value와 value가 다를 시 true |
이번에는 논리 연산자를 사용하여 2가지 이상의 조건을 만족하는 데이터를 조회하도록 해보자.
평균 키(height)가 165 이상이면서 인원(mem_number)가 6명보다 큰 멤버의 이름(mem_name)과 평균 키(height), 인원(mem_number)을 조회해보자.
<실행>
SELECT mem_name, height, mem_number
FROM member
WHERE height >= 165 AND mem_number > 6;
<결과>

height가 165 이상이고 mem_number가 6 초과인 데이터를 추출하기 위해 논리 연산자를 AND를 사용하여 데이터를 조회했다.
논리 연산자의 종류는 아래와 같다.
논리 연산자 | 사용 예 | 의미 |
|---|---|---|
| AND | expr1 AND expr2 | expr1과 expr2의 결과 모두 true일 때 true |
| OR | expr1 OR expr2 | expr1과 expr2의 결과 중 하나 이상 true일 때 true |
| NOT | NOT expr1 | expr1의 결과가 true이면 false, false이면 true |
| LIKE | LIKE %~_ | LIKE 뒤에 나오는 패턴에 부합하면 true, 후에 배울 예정 |
이번에는 평균 키(height)가 163 이상, 165 이하인 멤버들의 이름(mem_name)과 평균 키(height)를 조회해보도록 하자. 단순히 관계 연산자 2개를 써서 AND로 묶을 수 있지만, 수의 범위의 경우 BETWEEN AND를 통해 해결할 수 있다.
<실행>
SELECT mem_name, height FROM member WHERE height BETWEEN 163 AND 165;
<결과>

height가 163 이상이고 165 이하인 데이터 추출하기 위해 BETWEEN ~ AND를 사용하였다.
BETWEEN A AND B는 A 이상, B 이하인 데이터를 조회할 수 있다.
이번에는 특정 문자 집합에 속하는 문자를 찾아보자. 단순히 관계 연산자 =를 사용하여 조회할 수 있지만, 문자 집합이 커질수록 사용해야 하는 관계 연산자와 OR가 늘어난다. 따라서 이럴 때는 IN을 사용하는게 적합하다.
<실행>
SELECT mem_name, addr
FROM member
WHERE addr IN ('경기', '전남', '경남');
<결과>

addr이 경기거나 전남이거나 경남인 데이터를 조회하기 위해 IN ()을 사용하여 ()에 포함되는 값이 존재하는 데이터를 조회한다.
이번에는 앞서서 배운 논리 연산자 LIKE를 이용하여 원하는 형태의 문자열을 가진 데이터를 조회해보도록 하자.
<실행>
SELECT * FROM member WHERE mem_name LIKE '우%';
<결과>

mem_name의 제일 앞글자가 ‘우’인 모든 데이터를 조회하기 위해 LIKE를 사용하였다. LIKE는 문자열의 일부 글자 검색을 위해 사용하며, %는 무엇이든 허용한다는 의미이다.
만약 ‘%우’라면 mem_name이 ‘우’로 끝나는 데이터를 조회할 것이고, ‘우%우’라면 mem_name이 ‘우’로 시작하여 ‘우’로 끝나는 데이터를 조회할 것이다.
그렇다면, 허용하는 글자의 수를 제한하고 싶다면 어떻게 해야할까?
<실행>
SELECT * FROM member WHERE mem_name LIKE '__핑크';
<결과>

memname에서 앞 두 글자를 무엇이든 허용하고, 뒤가 ‘핑크’인 데이터 추출하기 위해 **``**(언더바)를 사용하였다. 언더바 하나는 한 글자는 무엇이 오든 허용이란 의미를 가진다. 따라서 __핑크 앞의 2글자는 어떤 글자가 되어도 되므로 에이, 블랙이 모두 true가 되어 추출되었다.
이번에는 서브 쿼리라는 개념에 대해 알아보자. 서브 쿼리란 말 그대로 쿼리 안에 존재하는 쿼리라는 뜻으로, 서브 쿼리는 앞서서 사용한 SELECT ~ FROM ~ WHERE ~을 SELECT, FROM, WHERE 뒤에 한번 더 사용하여 원하는 데이터를 내부적으로 한번 더 가져올 수 있다.
<실행>
SELECT mem_name, height
FROM member
WHERE height > (SELECT height
FROM member
WHERE mem_name = '에이핑크');
<결과>

주어진 쿼리에서, 에이핑크의 height보다 큰 height를 가진 데이터를 조회하기 위해 WHERE 뒤에 서브 쿼리를 사용하였다.
서브 쿼리를 사용하면 복잡한 조건을 서브 쿼리로 풀어낼 수 있지만, 연산 비용이 추가되고 여러 단점이 잇따라 오기 때문에 코딩테스트와 같은 특수한 환경이 아닌 이상 무작정 사용은 금해야 한다.