우재남님의 "혼자 공부하는 SQL"을 기반으로 학습한 게시물입니다.
📕 목차
1. SELECT, FROM, WHERE
2. SELECT 옵션
3. INSERT, UPDATE, DELETE
1. SELECT, FROM, WHERE
📌 USE
USE 데이터베이스_이름;
- 쿼리문을 사용하기 이전에 가장 먼저 사용할 데이터베이스를 지정하는 방법
- 다른 데이터베이스를 이용하려면 다시 USE 문을 사용하면 된다.
- USE를 사용하기 싫다면 (데이터베이스_이름).(테이블명)을 반복적으로 사용하면 된다.
📌 SELECT
SELECT 열_이름
FROM 테이블_이름
WHERE 조건식
GROUP BY 열_이름
HAVING 조건식
ORDER BY 열_이름
LIMIT 숫자
- SELECT 외엔 모두 생략 가능하다.
- 사용하게 된다면 순서가 중요해진다.
SELECT * FROM member;
- 애스터리스크(*)는 전체를 의미한다.
- 여기서 원하는 열만 선택하면 특정 column만 조회할 수 있다.
📌 Output 패널
- 초록색 체크 표시 : SQL 정상 실행
- 빨간색 X 표시 : SQL 오류
- # : 실행한 SQL 순번. 실행한 SQL이 여러 개면 점차 증가한다.
- Time : SQL을 실행한 시각
- Action : 실행된 SQL 표시
- Message : SELECT 문이 조회된 행의 개수. 오류 발생 시, 오류 번호 및 오류 메시지 표시
- Duration/Fetch : SQL 문이 실행되는데 걸린 시간(초), Fetch는 데이터베이스에서 가져온 시간(초)
📌 alias
SELECT addr 주소, debut_date "데뷔 일자", mem_name FROM member;
- 열 이름에 별칭(alias)를 지정할 수 있다.
- 테이블 명에도 같은 방식으로 별칭을 정할 수 있다.
📌 WHERE
• 관계 연산자, 논리 연산자
• BETWEEN ~ AND
• IN()
• LIKE
SELECT 열_이름 FROM 테이블_이름 WHERE 조건식;
- 특정 조건에 해당하는 결과만 조회하고 싶을 때 사용한다.
1️⃣ 관계 연산자, 논리 연산자의 사용
SELECT * FROM member WHERE height >= 165;
SELECT * FROM member WHERE height >= 165 AND mem_number > 6;
- 관계 연산자: <, <=, >=, >, =
- 논리 연산자: AND, OR
2️⃣ BETWEEN ~ AND
SELECT * FROM member WHERE height BETWEEN 163 AND 165;
- 163 <= height AND height <= 165와 동일하다.
3️⃣ IN()
SELECT * FROM member WHERE addr IN('경기', '전남');
- addr = '경기' OR addr = '전남'과 동일하다.
4️⃣ LIKE
SELECT * FROM member WHERE mem_name LIKE '우%';
- 문자열의 일부 글자를 검색할 때 사용
- '우'로 시작하는 모든(%) 문자열을 검색한다.
SELECT * FROM member WHERE mem_name LIKE '__핑크';
- 한 글자 매칭은 언더바를 사용한다.
📌 서브 쿼리 (Sub Query)
SELECT height FROM member WHERE mem_name = '에이핑크'; -- 164
SELECT mem_name, height FROM member WHERE height > 164;
- 특정 이름(mem_name)의 그룹명인 회원의 평균 키(height)보다 큰 회원을 검색하고 싶은 경우
- 두 쿼리 문을 합치는 방법 필요
SELECT mem_name, height FROM member
WHERE height > (SELECT height FROM member WHERE mem_name = '에이핑크');
- 출력값을 그대로 입력값으로 사용하기 위해 해당 위치에 쿼리문을 삽입하면 된다.
- 2개의 쿼리문을 하나로 줄여 관리하기가 편해졌다.
2. SELECT 옵션
• ORDER BY : 결과 정렬
• LIMIT : 결과 개수 제한
• DISTINCT : 중복 데이터 제거
• GROUP BY : 데이터 묶기
• HAVING : group by절에 쓰이는 where
📌 ORDER BY : 결과 정렬
SELECT mem_id, mem_name, debut_date FROM member ORDER BY debut_date; -- 오름차순
SELECT mem_id, mem_name, debut_date FROM member ORDER BY debut_date DESC; -- 내림차순
- 데뷔 일자(debut_date) 기준 정렬 방법
- DESC를 추가하면 역정렬 (기본값은 ASC)
SELECT mem_id, mem_name, debut_date, height
FROM member
where height >= 164
ORDER BY height >= 164 DESC, debut_date;
- ORDER BY절은 WHERE절 다음에 나와야 한다. (그렇지 않으면 query error)
- ORDER BY 정렬 기준은 여러 개 열로 지정 가능하다. (지정 순서 중요)
📌 LIMIT : 결과 개수 제한
SELECT * FROM member LIMIT 3;
SELECT * FROM member LIMIT 3, 2;
- LIMIT 시작, 개수 형식을 따른다.
- 인수를 하나만 넘기면 0부터 (개수)까지
📌 DISTINCT : 중복 데이터 제거
SELECT DISTINCT addr FROM member;
- 중복된 데이터를 제거하고 종류만 빠르게 파악할 수 있다.
📌 GROUP BY : 데이터 묶기
1️⃣ 집계 함수(aggregate function)
집계 함수 | 설명 |
SUM() | 합계 |
AVG() | 평균 |
MIN() | 최소값 |
MAX() | 최대값 |
COUNT() | 행의 개수 |
COUNT(DISTINCT) | 행의 개수(중복 허용 안함) |
2️⃣ 집계 함수와 GROUP BY
SELECT mem_id, SUM(amount) "총 구매 개수" FROM buy GROUP BY mem_id;
SELECT mem_id, SUM(amount * price) "총 구매 금액" FROM buy GROUP BY mem_id;
- 각 회원(mem_id)별로 구매한 개수(amount)를 집계 함수(SUM)로 합쳐서 조회
SELECT mem_id, AVG(amount) "평균 구매 개수" FROM buy;
SELECT mem_id, AVG(amount) "평균 구매 개수" FROM buy GROUP BY mem_id;
- GROUP BY를 적용하지 않았을 때는 전체에 대한 평균을 적용한다.
- GROUP BY mem_id 적용 시, 멤버 별 평균을 적용하여 결과를 산출한다.
📌 HAVING : group by절에 쓰이는 where
결과 중에 총 구매액이 1,000 이상인 회원을 고르기 위해 WHERE 절을 사용하면 에러가 발생한다.
오류 메시지에 따르면, 집계 함수는 WHERE 절에 나타날 수 없다.
SELECT mem_id, SUM(amount * price) "총 구매 금액"
FROM buy
GROUP BY mem_id
HAVING SUM(amount * price) > 1000;
- WHERE과 비슷한 개념이지만 집계 함수에 대해서 조건을 제한한다.
- HAVING 절은 반드시 GROUP BY 절 다음에 나와야 한다.
SELECT mem_id, SUM(amount * price) "총 구매 금액"
FROM buy
GROUP BY mem_id
HAVING SUM(amount * price) > 1000
ORDER BY SUM(amount * price) DESC;
- 결과를 정렬하고 싶다면 ORDER BY 절을 추가하면 된다.
3. INSERT, UPDATE, DELETE
📌 INSERT
INSERT INTO 테이블 [(열1, 열2, ...)] VALUES (값1, 값2, ...)
- 테이블 이름 다음의 열은 생략이 가능하다
- 만약 생략한다면 테이블을 정의할 때의 열 순서 및 개수와 동일해야 한다.
CREATE TABLE jayang (toy_id INT, toy_name CHAR(4), age INT);
INSERT INTO jayang VALUES(1, '화산', 18);
- 이렇게 하면 jayang이라는 테이블이 생성되고, 각각의 컬럼에 지정한 값이 들어간다.
- 만약, 나이 정보는 입력하고 싶지 않다고 무턱대고 정보를 빼면 sql error가 발생한다. (column이 매칭되지 않아서)
- age에 NULL값을 넣고 싶다면 컬럼명을 명시해야 한다.
INSERT INTO jayang (toy_id, toy_name) VALUES(2, 'null');
INSERT INTO jayang (age, toy_name, toy_id) VALUES(20, 'hye', 3);
- 열의 순서를 바꿔서 입력하고 싶다면 column명과 값을 순서에 맞게 작성해주면 된다.
더보기
✒️ AUTO_INCREMENT
이 내용이 왜 벌써 나오지..싶긴 한데, 나중에 설명하면 오히려 헷갈릴 수 있어서 그런가.
각 테이블마다 row를 구분하기 위한 고유값이 필요한데, 이는 보통 딱히 의미를 갖지 않는 대리 키를 사용한다.
1, 2, 3, 4, ...처럼 직접 적용하려면 제법 골치 아파지겠지만, 다행히 DBMS 별로 이런 기능들을 지원해준다.
MySQL에선 이걸 auto_increment라고 한다.
1️⃣ AUTO_INCREMENT 적용
DROP TABLE jayang;
CREATE TABLE jayang (
toy_id INT AUTO_INCREMENT PRIMARY KEY,
toy_name CHAR(4),
age INT
);
INSERT INTO jayang VALUES (NULL, '유저1', 10);
INSERT INTO jayang VALUES (NULL, '유저2', 15);
INSERT INTO jayang VALUES (NULL, '유저3', 20);
INSERT INTO jayang VALUES (NULL, '유저1', 10), (NULL, '유저2', 15), (NULL, '유저3', 20); -- 위랑 동일
- id 값을 NULL로 넣었지만, MySQL이 알아서 값을 증가시키면서 채워준다.
2️⃣ 시작값 바꾸기
ALTER TABLE jayang AUTO_INCREMENT = 100;
INSERT INTO jayang VALUES (NULL, '유저4', 25);
- 만약 자동 증가 시작값을 변경하고 싶다면, ALTER TABLE 예약어에서 auto_increment 값을 바꿔주면 된다.
SELECT LAST_INSERT_ID()
- LAST_INSERT_ID()는 현재 auto_increment 값을 알려준다.
3️⃣ 증감값 바꾸기
SET @@auto_increment_increment=3;
- 시스템 변수 자체를 변경하면 증감값을 바꿀 수도 있다.
✨ System variable
MySQL에서 자체적으로 가지고 있는 설정값이 저장된 변수
시스템 변수 앞에는 @@가 붙으며, SELECT 절로 확인 가능하다.
전체 시스템 변수 종류를 알고 싶다면 SHOW GLOBAL VARIABLES를 실행하면 된다.
CREATE TABLE city_popul (city_name CHAR(35), population INT);
INSERT INTO city_popul
SELECT Name, Population FROM world.city;
- 만약 기존에 존재하는 테이블에서 데이터를 가져오는 경우, INSERT INTO ~ SELECT문을 사용하면 된다.
📌 UPDATE
UPDATE 테이블_이름
SET 열1=값1, 열2=값2, ...
WHERE 조건;
- WHERE 절은 생략해도 되긴 하나, 테이블의 모든 행의 값이 변경된다. (일반적이지 않은 경우이므로 주의)
UPDATE jayang
SET toy_name="변경1"
WHERE age=10;
UPDATE jayang
SET toy_name="변경2", age=20
WHERE age=10;
- 한 번에 여러 열의 값을 변경할 수도 있다. (콤마로 구분)
📌 DELETE
DELETE FROM 테이블이름 WHERE 조건;
- UPDATE와 비슷하며, 행 단위로 삭제한다.
- WHERE 절이 없으면 모든 행 데이터가 삭제된다.
DELETE FROM jayang WHERE toy_id=2;
- 해당 sql문을 실행하면, 조건에 부합하는 모든 행을 제거한다.
DELETE FROM city_popul
WHERE city_name LIKE 'NEW%'
LIMIT 5;
- city_name이 "NEW"로 시작하는 상위 5건을 삭제하는 쿼리도 만들 수 있다.
📌 대용량 데이터 삭제
DELETE 문은 삭제가 오래 걸리기 때문에 데이터가 수억 건 이상이라면 다른 방법을 써야 한다.
DELETE FROM 테이블명;
DROP TABLE 테이블명;
TRUNCATE TABLE 테이블명;
- DELETE : 기존 방식. 가장 오래 걸린다.
- DROP : 테이블 자체를 삭제하므로 빠르다.
- TRUNCATE : DELETE와 동일한 효과를 내지만 매우 빠르다. (하지만 WHERE을 사용할 수 없다.)