Guider/Database/DatabaseDevGuide0002
Database#02

DatabaseDevGuide0002

SQL 기초 완전 정복

 

🗄️ DATABASE DEVELOPER GUIDE SERIES

DatabaseDevGuide0002

SQL 기초 완전 정복 A-Z

데이터베이스와 '대화'하는 언어, SQL을 처음부터 현업 수준까지 완전히 마스터하세요

⏱ 예상 학습: 20~30시간 📊 난이도: 초급~중급 🎯 목표: SQL 실무 완전 습득

📋 학습 목차

01 SQL이란? 데이터베이스와 대화하는 법
02 SELECT - 데이터 조회 완전 마스터
03 WHERE - 조건으로 데이터 필터링
04 ORDER BY & LIMIT - 정렬과 제한
05 INSERT INTO - 데이터 삽입
06 UPDATE SET - 데이터 수정
07 DELETE FROM - 데이터 삭제
08 MySQL 설치 및 실습 환경 구축
09 DDL - 테이블 생성/수정/삭제
10 집계 함수와 GROUP BY
11 실습 프로젝트: 학생 성적 관리 시스템
12 현업 면접 SQL Q&A + 로드맵
01

SQL이란? 데이터베이스와 대화하는 언어

💡 핵심 한 줄 요약

SQL(Structured Query Language)은 데이터베이스에서 데이터를 조회·삽입·수정·삭제하기 위해 사용하는 표준 언어입니다. 영어 문장처럼 읽히는 직관적인 구문이 특징입니다.

🤔 왜 SQL을 배워야 할까요?

🏆 세계 표준 언어

MySQL, PostgreSQL, Oracle, SQLite 등 모든 관계형 DB에서 공통으로 사용. 한 번 배우면 어디서든 사용 가능

💼 현업 필수 스킬

백엔드 개발자, 데이터 분석가, DBA 등 IT 직군 대부분에서 SQL 능력 필수. 채용 공고의 70% 이상 요구

📈 데이터 기반 의사결정

비즈니스 데이터 분석, 리포트 작성, 매출 집계 등 업무에서 SQL 없이는 불가능한 작업이 많음

⚡ 쉽고 강력함

SELECT * FROM users WHERE age > 20 처럼 영어 문장과 유사하여 비전공자도 빠르게 익힐 수 있음

📊 SQL 명령어의 4가지 분류 (DML/DDL/DCL/TCL)

분류 영문 Full Name 역할 주요 명령어
DML Data Manipulation Language 데이터 조작 (조회/삽입/수정/삭제) SELECT INSERT UPDATE DELETE
DDL Data Definition Language 구조 정의 (테이블 생성/수정/삭제) CREATE ALTER DROP TRUNCATE
DCL Data Control Language 권한 제어 (접근 권한 부여/회수) GRANT REVOKE
TCL Transaction Control Language 트랜잭션 제어 (커밋/롤백) COMMIT ROLLBACK SAVEPOINT

💡 이 가이드에서 집중할 내용: DML의 SELECT, INSERT, UPDATE, DELETE + DDL의 CREATE, ALTER, DROP을 완전히 마스터합니다!

01

SQL이란? — 데이터베이스와 대화하는 언어

💡 핵심 한 줄 요약

SQL(Structured Query Language)은 관계형 데이터베이스에 데이터를 저장·조회·수정·삭제하기 위해 사용하는 표준 언어입니다. "데이터베이스에게 한국어로 말 거는 것처럼" 명령하는 언어입니다!

😓 SQL 없이 데이터 찾기

  • 수백만 줄 파일을 처음부터 끝까지 읽기
  • 조건에 맞는 데이터를 일일이 비교
  • 원하는 데이터 찾는 데 수분~수시간
  • 동시에 여러 명이 작업하면 충돌 발생

😊 SQL로 데이터 찾기

  • 한 줄 명령으로 수백만 건 즉시 검색
  • 복잡한 조건도 자연어처럼 표현 가능
  • 0.001초 이내에 원하는 결과 반환
  • 수천 명 동시 접근해도 안전하게 처리

📊 SQL 명령어 4가지 분류 (DML / DDL / DCL / TCL)

분류 풀네임 역할 주요 명령어
DML Data Manipulation Language 데이터 조작 (일상적으로 가장 많이 사용) SELECTINSERTUPDATEDELETE
DDL Data Definition Language 테이블 구조 정의 (설계도 작성) CREATEALTERDROPTRUNCATE
DCL Data Control Language 접근 권한 제어 (보안 관리) GRANTREVOKE
TCL Transaction Control Language 트랜잭션 제어 (작업 확정/취소) COMMITROLLBACK

⚠️ SQL vs NoSQL 오해 바로잡기

SQL은 "언어"이고, MySQL·PostgreSQL은 "프로그램"입니다. SQL이라는 언어를 사용해서 MySQL/PostgreSQL/Oracle 등의 DBMS를 조작하는 것입니다. NoSQL은 SQL을 사용하지 않는 DB 방식의 총칭입니다.

02

SELECT - 데이터 조회 완전 마스터

💡 핵심 한 줄 요약

SELECT는 SQL에서 가장 많이 사용하는 명령어로, 데이터를 읽어오는(조회하는) 역할을 합니다. 현업에서 SQL 작업의 80% 이상이 SELECT입니다.

🏫 실습용 예시 테이블: students (학생 테이블)

id name grade score subject city
1 홍길동 3학년 92 수학 서울
2 김영희 2학년 85 영어 부산
3 이철수 1학년 78 수학 서울
4 박지수 3학년 96 국어 대구
5 최민준 2학년 71 영어 부산
6 정미나 1학년 88 국어 서울

👆 이 테이블을 기준으로 아래 모든 SELECT 예제를 실습합니다.

📌 SELECT 기본 문법 구조

-- SELECT 기본 구조 (대괄호 안은 선택사항)

SELECT column1, column2, ... -- 조회할 열 (컬럼)

FROM table_name -- 조회할 테이블

[WHERE 조건] -- 필터링 조건 (선택)

[ORDER BY column ASC|DESC] -- 정렬 (선택)

[LIMIT n] -- 가져올 행 수 제한 (선택)

예제 SQL 코드 결과 설명
모든 컬럼 조회 SELECT * FROM students; 전체 6행 모든 컬럼 반환
특정 컬럼만 조회 SELECT name, score FROM students; 이름과 점수 2개 컬럼만 반환
컬럼에 별칭 붙이기 (AS) SELECT name AS 이름, score AS 점수 FROM students; 결과 헤더를 '이름', '점수'로 표시
중복 제거 조회 (DISTINCT) SELECT DISTINCT city FROM students; 서울/부산/대구 3개 고유값만 반환
계산식 사용 SELECT name, score * 1.1 AS 보정점수 FROM students; 점수에 10% 가산하여 보정점수 컬럼으로 표시

⚠️ 현업에서 SELECT * 사용 시 주의!

SELECT * 는 공부할 때는 편리하지만, 현업에서는 필요한 컬럼만 명시하는 것이 원칙입니다. 불필요한 데이터 전송으로 네트워크 부하가 증가하고, 코드 가독성이 떨어지며, 스키마 변경 시 예기치 않은 오류가 발생할 수 있습니다.

02

SELECT — 데이터 조회 완전 마스터

💡 SELECT란?

SELECT는 SQL의 꽃! 데이터베이스에서 원하는 데이터를 읽어오는 명령어입니다. 현업에서 SQL의 80%는 SELECT입니다.

📋 실습에 사용할 샘플 테이블

이번 가이드 전체에서 이 세 가지 테이블을 사용합니다. 먼저 눈에 익혀두세요!

👤 users 테이블 (회원 정보)

id name email age grade created_at
1 홍길동 hong@test.com 28 VIP 2024-01-15
2 김영희 kim@test.com 34 일반 2024-02-20
3 이철수 lee@test.com 25 골드 2024-03-10
4 박민수 park@test.com 42 VIP 2024-04-05
5 최지현 choi@test.com 19 일반 2024-05-22

🛒 orders 테이블 (주문 정보)

order_id user_id product_name amount status order_date
1001 1 노트북 1500000 완료 2024-06-01
1002 2 마우스 35000 완료 2024-06-03
1003 1 키보드 85000 배송중 2024-06-10
1004 3 모니터 320000 완료 2024-06-15
1005 4 웹캠 72000 취소 2024-06-20

🔍 SELECT 기본 문법 완전 해부

SQL SYNTAX — SELECT 기본 구조

SELECT   컬럼1, 컬럼2, ...   -- 가져올 컬럼 지정 (* = 전체)
FROM     테이블명             -- 어느 테이블에서
WHERE    조건                 -- 조건 필터링 (없으면 전체)
ORDER BY 컬럼명 ASC|DESC     -- 정렬 방식
LIMIT    숫자                 -- 가져올 행 수 제한

📌 SELECT 실전 예제 모음

✅ 예제 1 — 모든 회원 전체 조회

SELECT *
FROM users;
-- * 는 '모든 컬럼'을 의미합니다. 실무에서는 필요한 컬럼만 지정하는 것이 성능상 유리!

📤 결과: users 테이블의 모든 행(5건)과 모든 컬럼 반환

✅ 예제 2 — 특정 컬럼만 조회 (이름, 이메일, 등급)

SELECT name, email, grade
FROM users;

📤 결과: name, email, grade 3개 컬럼만 반환 (성능 최적화에 중요)

✅ 예제 3 — 별칭(ALIAS) 사용으로 컬럼명 변경

SELECT
    name AS '회원이름',
    email AS '이메일주소',
    age AS '나이'
FROM users;
-- AS 키워드로 결과 컬럼명을 원하는 이름으로 바꿀 수 있습니다

📤 결과: 컬럼명이 '회원이름', '이메일주소', '나이'로 표시됨

✅ 예제 4 — DISTINCT로 중복 제거

SELECT DISTINCT grade
FROM users;
-- 결과: 'VIP', '일반', '골드' — 중복 없이 고유한 등급만 조회

📤 결과: VIP, 일반, 골드 — 3가지 고유 등급값만 반환 (중복 제거)

✅ 예제 5 — 계산식 사용 (컬럼 연산)

SELECT
    product_name,
    amount,
    amount * 0.1 AS '부가세(10%)',
    amount * 1.1 AS '부가세포함금액'
FROM orders;
-- SELECT에서 사칙연산(+, -, *, /) 가능!

📤 결과: 각 주문별로 원래 금액, 부가세, 총금액이 계산되어 출력

03

WHERE - 조건으로 데이터 필터링

💡 핵심 한 줄 요약

WHERE는 조건을 지정해서 원하는 데이터만 골라내는 절입니다. SQL에서 WHERE를 잘 쓸수록 빠르고 정확한 쿼리를 작성할 수 있습니다.

📌 비교 연산자 완전 정리

연산자 의미 SQL 예제 결과
= 같다 WHERE city = '서울' 서울에 사는 학생만
<> 또는 != 같지 않다 WHERE subject <> '수학' 수학 과목 제외한 학생
> 크다 WHERE score > 85 85점 초과 학생 (홍길동, 박지수, 정미나)
>= 크거나 같다 WHERE score >= 85 85점 이상 학생 (+ 김영희 포함)
BETWEEN 범위 조건 WHERE score BETWEEN 80 AND 90 80~90점 구간 (80, 90 포함)
IN 목록 중 하나 WHERE city IN ('서울', '부산') 서울 또는 부산 학생
NOT IN 목록 제외 WHERE city NOT IN ('서울') 서울 제외 학생
LIKE 패턴 검색 WHERE name LIKE '김%' '김'으로 시작하는 이름 (김영희)
IS NULL NULL 여부 검사 WHERE email IS NULL 이메일이 없는 행

🔗 논리 연산자 AND, OR, NOT

-- AND: 두 조건 모두 만족

SELECT * FROM students

WHERE score >= 85 AND city = '서울';

-- 결과: 홍길동(92점, 서울), 정미나(88점, 서울)

 

-- OR: 두 조건 중 하나만 만족

SELECT * FROM students

WHERE city = '서울' OR score >= 90;

-- 결과: 서울 학생 + 90점 이상 학생

 

-- NOT: 조건 부정

SELECT * FROM students WHERE NOT subject = '수학';

-- 결과: 수학 과목이 아닌 학생들

🎯 LIKE 와일드카드 완전 정리

와일드카드 의미 예제 매칭되는 예시
% 0개 이상의 아무 문자 LIKE '김%' 김영희, 김철수, 김a, 김
% 끝에 특정 문자 LIKE '%희' 김영희, 민희, 희
% 중간에 특정 문자 포함 LIKE '%영%' 김영희, 영민, 이영수
_ 정확히 1개의 아무 문자 LIKE '김__' 김영희 (3글자 이름), 김철수
04

ORDER BY & LIMIT - 정렬과 결과 제한

📶 ORDER BY 정렬

-- 점수 오름차순 (낮은 점수부터)

SELECT name, score

FROM students

ORDER BY score ASC;

-- 점수 내림차순 (높은 점수부터)

SELECT name, score

FROM students

ORDER BY score DESC;

📏 LIMIT 결과 제한

-- 상위 3명만 조회 (TOP 3)

SELECT name, score

FROM students

ORDER BY score DESC

LIMIT 3;

-- 페이지네이션 (4번째부터 3개)

SELECT name, score

FROM students

LIMIT 3 OFFSET 3;

📌 복합 정렬 예제 (다중 컬럼 정렬)

-- 도시별 오름차순, 같은 도시면 점수 내림차순

SELECT name, city, score FROM students ORDER BY city ASC, score DESC;

03

WHERE — 조건으로 데이터 필터링

💡 WHERE란?

WHERE는 "조건에 맞는 행(Row)만 가져오세요"라는 필터입니다. 수백만 건 데이터 중 내가 원하는 데이터만 정확하게 뽑아낼 수 있습니다.

📌 WHERE 조건 연산자 완전 정리

연산자 의미 예시 결과
= 같다 WHERE grade = 'VIP' 등급이 VIP인 회원
!= 또는 <> 같지 않다 WHERE grade != 'VIP' VIP가 아닌 회원
> < >= <= 크다/작다/이상/이하 WHERE age >= 30 나이가 30 이상인 회원
BETWEEN A AND B A와 B 사이 (포함) WHERE age BETWEEN 20 AND 30 20세 이상 30세 이하
IN (값1, 값2, ...) 목록 중 하나와 일치 WHERE grade IN ('VIP','골드') VIP 또는 골드 회원
NOT IN 목록 중 어느 것도 아닌 WHERE grade NOT IN ('VIP') VIP가 아닌 모든 회원
LIKE '패턴' 패턴 일치 검색 WHERE email LIKE '%@gmail%' gmail 포함 이메일
IS NULL NULL인 데이터 WHERE phone IS NULL 전화번호 없는 회원
IS NOT NULL NULL이 아닌 데이터 WHERE phone IS NOT NULL 전화번호 있는 회원
AND 두 조건 모두 참 WHERE age >= 30 AND grade='VIP' 30세 이상이면서 VIP
OR 둘 중 하나라도 참 WHERE grade='VIP' OR grade='골드' VIP이거나 골드인 회원

📌 LIKE 패턴 와일드카드 상세

패턴 의미 예시 매칭 예
% 0개 이상 임의 문자 LIKE '김%' 김, 김영희, 김철수, 김민준...
% 끝에 '~'으로 끝나는 LIKE '%수' 철수, 영수, 민수...
%..% 중간에 포함 LIKE '%test%' test포함 모든 이메일
_ 정확히 1개 문자 LIKE '김_수' 김철수, 김민수 (3글자만)

📌 WHERE 복합 조건 실전 예제

예제: 30세 이상이면서 VIP 등급인 회원의 이름과 이메일 조회

SELECT name, email, age, grade
FROM users
WHERE age >= 30
  AND grade = 'VIP';
-- 결과: 박민수 (42세, VIP) 1건 반환

예제: '김' 또는 '이'씨 성을 가진 회원 조회

SELECT name, email
FROM users
WHERE name LIKE '김%'
   OR name LIKE '이%';
-- 결과: 김영희, 이철수 2건 반환

예제: 주문금액이 50,000원 이상 500,000원 이하이고 완료 상태인 주문

SELECT order_id, product_name, amount, status
FROM orders
WHERE amount BETWEEN 50000 AND 500000
  AND status = '완료';
-- 결과: 마우스(35000 제외), 키보드(배송중 제외), 모니터(320000 완료) → 모니터 1건

⚠️ 현업 주의사항 — AND와 OR 우선순위

-- ❌ 의도와 다른 결과 (AND가 OR보다 먼저 실행됨!)
WHERE age >= 30 OR grade = 'VIP' AND status = '완료'

-- ✅ 괄호로 명확하게 우선순위 지정
WHERE (age >= 30 OR grade = 'VIP') AND status = '완료'

AND는 OR보다 연산 우선순위가 높습니다. 복합 조건 시 반드시 괄호()로 명확히 구분하세요!

05

INSERT INTO - 데이터 삽입 완전 정복

💡 핵심 한 줄 요약

INSERT INTO는 테이블에 새로운 데이터(행)를 추가하는 명령어입니다. 회원가입, 주문 접수, 게시글 작성 등 모든 '데이터 입력' 상황에 사용됩니다.

📌 INSERT 기본 문법과 다양한 사용법

-- 방법 1: 컬럼명 명시 (권장 방법)

INSERT INTO students (name, grade, score, subject, city)

VALUES ('강민서', '2학년', 90, '수학', '인천');

-- 방법 2: 컬럼 순서대로 전부 입력 (컬럼명 생략)

INSERT INTO students

VALUES (7, '강민서', '2학년', 90, '수학', '인천');

-- 방법 3: 여러 행 한번에 삽입 (다중 INSERT, 성능 좋음)

INSERT INTO students (name, grade, score, subject, city)

VALUES

('강민서', '2학년', 90, '수학', '인천'),

('오지훈', '3학년', 83, '영어', '광주'),

('서예린', '1학년', 95, '국어', '서울');

✅ INSERT 올바른 습관

  • 컬럼명을 항상 명시할 것
  • 여러 행 삽입 시 다중 INSERT 사용
  • AUTO_INCREMENT ID는 생략 가능
  • DEFAULT 값 있는 컬럼 생략 가능

❌ INSERT 주의사항

  • NOT NULL 컬럼은 반드시 값 제공
  • PK 중복 시 오류 발생
  • UNIQUE 제약 위반 시 오류
  • 데이터 타입 불일치 주의
06

UPDATE SET - 데이터 수정 완전 정복

⚠️ 절대 절대 잊지 마세요!

UPDATE는 반드시 WHERE 조건을 함께 사용해야 합니다. WHERE 없이 UPDATE하면 테이블의 모든 행이 수정되는 대참사가 발생합니다!

📌 UPDATE 문법과 실전 예제

-- 기본 구조

UPDATE 테이블명

SET 컬럼1 = 값1, 컬럼2 = 값2

WHERE 조건; -- ← 필수!! 없으면 전체 수정!!

-- 예제 1: 특정 학생의 점수 수정

UPDATE students

SET score = 95

WHERE id = 3; -- id가 3인 이철수의 점수만 수정

-- 예제 2: 여러 컬럼 동시 수정

UPDATE students

SET score = 80, city = '대전'

WHERE name = '최민준';

-- 예제 3: 조건부 일괄 수정 (점수 10점 가산)

UPDATE students

SET score = score + 10

WHERE subject = '영어'; -- 영어 수강생 전체 10점 가산

🚨 실제 현업에서 발생한 사고 사례

-- ❌ WHERE를 빠뜨린 대참사

UPDATE users SET password = 'new_password'; -- 모든 사용자 비밀번호가 동일하게 변경!!

💡 해결책: UPDATE 전 반드시 SELECT로 먼저 대상을 확인하고, 트랜잭션(BEGIN; ... COMMIT;)과 함께 사용하는 습관을 들이세요!

07

DELETE FROM - 데이터 삭제 완전 정복

🚨 DELETE는 되돌릴 수 없습니다!

DELETE도 UPDATE와 마찬가지로 WHERE 조건 없이 실행하면 테이블의 모든 데이터가 삭제됩니다. 반드시 WHERE를 명시하고, 중요한 삭제는 트랜잭션으로 감싸세요.

📌 DELETE 문법과 실전 예제

-- 기본 구조

DELETE FROM 테이블명

WHERE 조건; -- ← 필수!! 없으면 전체 삭제!!

-- 예제 1: 특정 학생 삭제

DELETE FROM students

WHERE id = 5; -- id가 5인 최민준만 삭제

-- 예제 2: 조건부 삭제 (60점 미만 학생 삭제)

DELETE FROM students

WHERE score < 60;

-- 안전한 삭제 패턴 (트랜잭션 사용)

BEGIN; -- 트랜잭션 시작

SELECT * FROM students WHERE id = 5; -- 먼저 확인

DELETE FROM students WHERE id = 5; -- 삭제

COMMIT; -- 확인 후 확정 (문제 시 ROLLBACK;)

⚖️ DELETE vs TRUNCATE vs DROP 비교

명령어 삭제 대상 롤백 가능? 사용 시나리오
DELETE 조건에 맞는 행(들) ✅ 가능 특정 데이터 삭제, 조건부 삭제
TRUNCATE 테이블의 모든 데이터 ❌ 불가 테이블 초기화 (구조는 유지)
DROP 테이블 자체를 삭제 ❌ 불가 테이블 구조까지 완전 제거
04

ORDER BY & LIMIT — 정렬과 제한

💡 ORDER BY란?

ORDER BY는 조회 결과를 특정 컬럼을 기준으로 오름차순(ASC) 또는 내림차순(DESC)으로 정렬합니다. LIMIT는 결과 수를 제한합니다. "가장 최근 주문 10개만 보여줘" 같은 요구에 필수입니다!

예제 1: 나이 오름차순 정렬 (어린 순)

SELECT name, age, grade
FROM users
ORDER BY age ASC;  -- ASC = 오름차순 (기본값, 생략 가능)
-- 결과: 최지현(19), 이철수(25), 홍길동(28), 김영희(34), 박민수(42)

예제 2: 주문금액 내림차순 정렬 (비싼 순)

SELECT product_name, amount, status
FROM orders
ORDER BY amount DESC;  -- DESC = 내림차순
-- 결과: 노트북(150만), 모니터(32만), 키보드(8.5만), 웹캠(7.2만), 마우스(3.5만)

예제 3: LIMIT으로 상위 3건만 조회 (Top 3)

SELECT product_name, amount
FROM orders
ORDER BY amount DESC
LIMIT 3;  -- 상위 3건만!
-- 결과: 노트북(150만), 모니터(32만), 키보드(8.5만)

예제 4: LIMIT + OFFSET으로 페이징 처리 (현업 필수!)

-- 게시판 2페이지: 1페이지(1~10번)를 건너뛰고 11~20번 조회
SELECT *
FROM posts
ORDER BY created_at DESC
LIMIT 10 OFFSET 10;  -- 10개씩, 10번 건너뛰기

-- 공식: OFFSET = (페이지번호 - 1) × 페이지당건수
-- 1페이지: LIMIT 10 OFFSET 0
-- 2페이지: LIMIT 10 OFFSET 10
-- 3페이지: LIMIT 10 OFFSET 20

예제 5: 다중 컬럼 정렬 (복합 정렬)

-- 등급 오름차순 → 같은 등급 내에서 나이 내림차순
SELECT name, age, grade
FROM users
ORDER BY grade ASC, age DESC;
-- 쉼표(,)로 여러 기준 지정 가능!
05

INSERT INTO — 데이터 삽입 완전 마스터

💡 INSERT INTO란?

INSERT INTO는 테이블에 새 행(Row)을 추가하는 명령어입니다. 회원가입, 글 작성, 주문 생성 등 모든 "데이터 생성" 작업에 사용됩니다.

📋 INSERT 문법 패턴 3가지

패턴 1: 기본형 — 컬럼 지정 후 값 삽입 (권장!)

INSERT INTO users (name, email, age, grade)
VALUES ('정다은', 'jung@test.com', 27, '일반');
-- 컬럼 순서를 명시하면 테이블 구조가 변경되어도 안전!

패턴 2: 다중 행 삽입 — 한 번에 여러 건 INSERT

INSERT INTO users (name, email, age, grade)
VALUES
  ('강민준', 'kang@test.com', 31, '골드'),
  ('윤서연', 'yoon@test.com', 26, '일반'),
  ('조현우', 'cho@test.com', 38, 'VIP');
-- 한 번의 쿼리로 3건 동시 삽입! 성능상 유리합니다.

패턴 3: INSERT ... SELECT — 다른 테이블 데이터로 삽입

-- VIP 회원을 별도 VIP 전용 테이블로 복사
INSERT INTO vip_users (name, email)
SELECT name, email
FROM users
WHERE grade = 'VIP';
-- SELECT 결과를 그대로 다른 테이블에 삽입!

⚠️ INSERT 주의사항 (현업 실수 TOP 3)

실수 유형 잘못된 코드 올바른 코드
중복 이메일 삽입 VALUES ('hong@test.com') INSERT IGNORE 또는 ON DUPLICATE KEY
컬럼명 생략 INSERT INTO users VALUES (...) INSERT INTO users (col1,...)
NULL 허용 안되는 컬럼 name 컬럼 누락 NOT NULL 컬럼은 반드시 포함
08

MySQL 설치 및 실습 환경 구축

🛠 실습 환경 3가지 선택지

🐬

MySQL Workbench

PC에 직접 설치. 가장 실무에 가까운 환경

⭐ 추천

🦆

DBeaver (무료)

다양한 DB 지원. 현업에서 많이 사용

현업 인기

☁️

DB Fiddle (온라인)

설치 없이 브라우저에서 바로 실습

빠른 시작

📋 MySQL + DBeaver 설치 단계 (Windows/Mac 공통)

단계 작업 URL / 메모
1 MySQL Community 다운로드 dev.mysql.com/downloads → MySQL Installer 선택
2 설치 시 "Developer Default" 선택 MySQL Server + Workbench 한 번에 설치됨
3 root 비밀번호 설정 반드시 기억! 잊으면 재설치 필요
4 DBeaver Community 다운로드 (선택) dbeaver.io → Community Edition (무료)
5 첫 데이터베이스 생성 CREATE DATABASE mydb; USE mydb;

🚀 첫 실습: 데이터베이스 생성부터 데이터 입력까지

-- 1단계: 데이터베이스 생성 및 선택

CREATE DATABASE school_db;

USE school_db;

-- 2단계: 테이블 생성

CREATE TABLE students (

id INT AUTO_INCREMENT PRIMARY KEY,

name VARCHAR(50) NOT NULL,

grade VARCHAR(10) NOT NULL,

score INT DEFAULT 0,

subject VARCHAR(20),

city VARCHAR(20),

created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP

);

-- 3단계: 데이터 삽입

INSERT INTO students (name, grade, score, subject, city) VALUES

('홍길동', '3학년', 92, '수학', '서울'),

('김영희', '2학년', 85, '영어', '부산'),

('이철수', '1학년', 78, '수학', '서울'),

('박지수', '3학년', 96, '국어', '대구');

-- 4단계: 결과 확인

SELECT * FROM students;

06

UPDATE SET — 데이터 수정 완전 마스터

💡 UPDATE란?

UPDATE는 이미 존재하는 데이터를 수정하는 명령어입니다. 반드시 WHERE와 함께 사용하세요! WHERE 없이 실행하면 테이블 전체가 수정되는 대참사가 발생합니다!

🚨 절대 주의! UPDATE는 WHERE 없이 실행 금지!

-- ❌ 절대 금지: WHERE 없는 UPDATE → 모든 회원 등급이 VIP가 됨!
UPDATE users SET grade = 'VIP';

-- ✅ 올바른 방법: WHERE로 대상 특정!
UPDATE users SET grade = 'VIP' WHERE id = 2;

📌 UPDATE 실전 예제 모음

예제 1: 단일 컬럼 수정 — 특정 회원 등급 변경

UPDATE users
SET grade = 'VIP'
WHERE id = 2;
-- id가 2인 김영희의 등급만 VIP로 변경

예제 2: 여러 컬럼 동시 수정

UPDATE users
SET
  email = 'kim_new@test.com',
  grade = '골드',
  updated_at = NOW()  -- NOW()는 현재 시각 자동 입력
WHERE id = 2;

예제 3: 계산식으로 수정 — 주문금액 10% 할인

UPDATE orders
SET amount = amount * 0.9  -- 기존값의 90% (10% 할인)
WHERE status = '배송중';
-- 배송중인 주문만 10% 할인 적용

예제 4: CASE WHEN으로 조건별 다른 값 설정 (현업 자주 사용!)

-- 나이에 따라 등급 자동 분류
UPDATE users
SET grade = CASE
  WHEN age >= 40 THEN 'VIP'
  WHEN age >= 30 THEN '골드'
  ELSE '일반'
END;
-- IF-ELSE처럼 조건별로 다른 값 설정 가능!
07

DELETE FROM — 데이터 삭제 완전 마스터

💡 DELETE란?

DELETE는 테이블에서 행(Row)을 삭제하는 명령어입니다. UPDATE와 마찬가지로 반드시 WHERE와 함께! 삭제된 데이터는 ROLLBACK 없이는 복구 불가능합니다.

📊 DELETE vs TRUNCATE vs DROP 비교

명령어 삭제 범위 WHERE 사용 ROLLBACK 테이블 구조 속도
DELETE 조건에 맞는 행만 ✅ 가능 ✅ 가능 유지됨 느림
TRUNCATE 전체 행 ❌ 불가 ❌ 불가 유지됨 (초기화) 빠름
DROP 테이블 자체 삭제 ❌ 불가 ❌ 불가 삭제됨 빠름

예제 1: 특정 주문 삭제

DELETE FROM orders
WHERE order_id = 1005;
-- 취소된 주문(order_id=1005) 삭제

예제 2: 조건 삭제 — 취소 상태 주문 전체 삭제

DELETE FROM orders
WHERE status = '취소';
-- 현업에서는 실제 삭제보다 status = '취소'로 소프트 삭제를 선호!

예제 3: 현업 패턴 — 소프트 삭제 (Soft Delete)

-- 실제 삭제 대신 is_deleted 플래그만 변경 (복구 가능!)
UPDATE users
SET
  is_deleted = 1,
  deleted_at = NOW()
WHERE id = 3;

-- 조회 시 삭제된 데이터 제외
SELECT * FROM users WHERE is_deleted = 0;

💼 현업 꿀팁 — Soft Delete가 표준인 이유

대부분의 서비스에서는 실제 DELETE 대신 is_deleted = 1 또는 deleted_at 타임스탬프를 통한 소프트 삭제를 사용합니다. 이유는: ① 데이터 복구 가능 ② 통계/분석에 활용 ③ 규정 준수(개인정보 보관 의무). 실제 DELETE는 로그/임시 데이터 정리 등에만 사용합니다.

09

DDL - 테이블 생성, 수정, 삭제 완전 정복

📌 CREATE TABLE - 테이블 구조 설계

-- 현업 수준의 사용자 테이블 설계 예시

CREATE TABLE users (

user_id INT AUTO_INCREMENT, -- 자동 증가 정수 ID

username VARCHAR(50) NOT NULL UNIQUE, -- 중복 불가, 필수

email VARCHAR(100) NOT NULL UNIQUE, -- 이메일 중복 불가

password VARCHAR(255) NOT NULL, -- 해시값 저장 (보안)

age INT CHECK (age >= 0 AND age <= 150),

status ENUM('active','inactive','banned') DEFAULT 'active',

created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

PRIMARY KEY (user_id)

);

🔧 ALTER TABLE - 기존 테이블 구조 변경

-- 컬럼 추가

ALTER TABLE students ADD COLUMN phone VARCHAR(20);

-- 컬럼 타입 변경

ALTER TABLE students MODIFY COLUMN score DECIMAL(5,2);

-- 컬럼 이름 변경 (MySQL 8.0+)

ALTER TABLE students RENAME COLUMN grade TO school_year;

-- 컬럼 삭제

ALTER TABLE students DROP COLUMN phone;

📊 자주 쓰는 데이터 타입 + AUTO_INCREMENT 정리

컬럼 용도 권장 타입 예제 이유
기본키 ID INT AUTO_INCREMENT id INT AUTO_INCREMENT PK 자동으로 1씩 증가
이름, 제목 VARCHAR(50~255) name VARCHAR(50) 가변 길이, 공간 효율적
금액, 가격 DECIMAL(10,2) price DECIMAL(10,2) 정확한 소수, FLOAT 금지!
긴 텍스트 TEXT content TEXT 게시글, 댓글 본문
상태값 ENUM('a','b','c') status ENUM('on','off') 정해진 값만 허용, 공간 절약
생성/수정일시 TIMESTAMP DEFAULT NOW() created_at TIMESTAMP 자동으로 현재 시간 저장
10

집계 함수와 GROUP BY - 데이터 요약

💡 핵심 한 줄 요약

집계 함수는 여러 행의 데이터를 하나의 결과값으로 계산합니다. GROUP BY와 함께 사용하면 강력한 데이터 분석이 가능합니다.

📊 핵심 집계 함수 5가지

함수 역할 SQL 예제 결과
COUNT(*) 전체 행 수 세기 SELECT COUNT(*) FROM students; 6 (전체 학생 수)
SUM(col) 합계 계산 SELECT SUM(score) FROM students; 510 (전체 점수 합)
AVG(col) 평균 계산 SELECT AVG(score) FROM students; 85 (평균 점수)
MAX(col) 최댓값 SELECT MAX(score) FROM students; 96 (최고 점수)
MIN(col) 최솟값 SELECT MIN(score) FROM students; 71 (최저 점수)

-- GROUP BY: 그룹별로 집계

-- 과목별 평균 점수와 학생 수 조회

SELECT

subject AS 과목,

COUNT(*) AS 학생수,

ROUND(AVG(score), 1) AS 평균점수,

MAX(score) AS 최고점,

MIN(score) AS 최저점

FROM students

GROUP BY subject

ORDER BY 평균점수 DESC;

-- HAVING: GROUP BY 결과에 조건 추가 (WHERE와 차이!)

-- 평균 점수 85점 이상인 과목만 조회

SELECT subject, AVG(score) AS 평균점수

FROM students

GROUP BY subject

HAVING AVG(score) >= 85; -- WHERE가 아닌 HAVING 사용!

📌 WHERE vs HAVING 핵심 차이

구분 WHERE HAVING
적용 시점 GROUP BY 이전 (개별 행 필터) GROUP BY 이후 (그룹 필터)
집계함수 사용 ❌ 불가 ✅ 가능
예시 WHERE score >= 80 HAVING AVG(score) >= 80
08

MySQL 설치 및 실습 환경 구축

🖥️ 실습 환경 구성 (Windows / Mac 공통)

🐬

MySQL

관계형 DB 엔진 (무료)

필수 설치
🦫

DBeaver

GUI 관리 도구 (무료)

권장 설치
💻

VS Code

SQL 파일 편집 (무료)

선택 설치

📋 실습용 데이터베이스 + 테이블 생성 SQL (복사해서 바로 실행!)

STEP 1 — 데이터베이스 생성 및 선택

-- 실습용 데이터베이스 생성
CREATE DATABASE practice_db
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_unicode_ci;  -- 한글 지원!

-- 생성한 데이터베이스 선택
USE practice_db;

STEP 2 — users 테이블 생성

CREATE TABLE users (
  id         INT           AUTO_INCREMENT PRIMARY KEY,  -- 자동증가 기본키
  name       VARCHAR(50)   NOT NULL,                      -- 이름 필수
  email      VARCHAR(100)  NOT NULL UNIQUE,               -- 이메일 중복불가
  age        INT           CHECK (age >= 0 AND age <= 150), -- 나이 범위 제한
  grade      VARCHAR(20)   DEFAULT '일반',                  -- 기본 등급
  is_deleted TINYINT(1)   DEFAULT 0,                       -- 소프트 삭제용
  created_at TIMESTAMP    DEFAULT CURRENT_TIMESTAMP,    -- 생성 시각 자동
  updated_at TIMESTAMP    DEFAULT CURRENT_TIMESTAMP
                         ON UPDATE CURRENT_TIMESTAMP   -- 수정 시각 자동
);

STEP 3 — orders 테이블 생성 (외래키 포함)

CREATE TABLE orders (
  order_id     INT              AUTO_INCREMENT PRIMARY KEY,
  user_id      INT              NOT NULL,
  product_name VARCHAR(200)     NOT NULL,
  amount       DECIMAL(12, 0)   NOT NULL,              -- 금액은 DECIMAL 필수!
  status       VARCHAR(20)      DEFAULT '대기',
  order_date   TIMESTAMP        DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (user_id) REFERENCES users(id)   -- FK 설정!
    ON DELETE RESTRICT   -- 회원 삭제 시 주문 있으면 거부
    ON UPDATE CASCADE    -- 회원 ID 변경 시 자동 반영
);

STEP 4 — 샘플 데이터 삽입

INSERT INTO users (name, email, age, grade) VALUES
  ('홍길동', 'hong@test.com', 28, 'VIP'),
  ('김영희', 'kim@test.com', 34, '일반'),
  ('이철수', 'lee@test.com', 25, '골드'),
  ('박민수', 'park@test.com', 42, 'VIP'),
  ('최지현', 'choi@test.com', 19, '일반');

INSERT INTO orders (user_id, product_name, amount, status) VALUES
  (1, '노트북', 1500000, '완료'),
  (2, '마우스', 35000, '완료'),
  (1, '키보드', 85000, '배송중'),
  (3, '모니터', 320000, '완료'),
  (4, '웹캠', 72000, '취소');
11

실습 프로젝트: 학생 성적 관리 시스템

🎯 프로젝트 목표

이번에 배운 모든 SQL을 종합하여 실제로 동작하는 학생 성적 관리 시스템을 처음부터 만들어봅니다. 이 실습을 완료하면 SQL 기초를 완전히 체득할 수 있습니다.

📐 시스템 구조 (3개 테이블)

📋 students (학생)

student_id (PK)
name
grade
city
created_at

📚 subjects (과목)

subject_id (PK)
subject_name
teacher

📊 scores (성적)

score_id (PK)
student_id (FK)
subject_id (FK)
score
exam_date

-- ① 데이터베이스 생성

CREATE DATABASE grade_management;

USE grade_management;

-- ② students 테이블 생성

CREATE TABLE students (

student_id INT AUTO_INCREMENT PRIMARY KEY,

name VARCHAR(50) NOT NULL,

grade VARCHAR(10) NOT NULL,

city VARCHAR(20),

created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP

);

-- ③ subjects 테이블 생성

CREATE TABLE subjects (

subject_id INT AUTO_INCREMENT PRIMARY KEY,

subject_name VARCHAR(30) NOT NULL UNIQUE,

teacher VARCHAR(50)

);

-- ④ scores 테이블 생성 (외래키 포함)

CREATE TABLE scores (

score_id INT AUTO_INCREMENT PRIMARY KEY,

student_id INT NOT NULL,

subject_id INT NOT NULL,

score INT CHECK (score >= 0 AND score <= 100),

exam_date DATE NOT NULL,

FOREIGN KEY (student_id) REFERENCES students(student_id),

FOREIGN KEY (subject_id) REFERENCES subjects(subject_id)

);

-- ⑤ 샘플 데이터 삽입

INSERT INTO students (name, grade, city) VALUES

('홍길동', '3학년', '서울'), ('김영희', '2학년', '부산'),

('이철수', '1학년', '서울'), ('박지수', '3학년', '대구');

INSERT INTO subjects (subject_name, teacher) VALUES

('수학', '김선생'), ('영어', '이선생'), ('국어', '박선생');

INSERT INTO scores (student_id, subject_id, score, exam_date) VALUES

(1, 1, 92, '2024-03-15'), (1, 2, 78, '2024-03-15'),

(2, 2, 85, '2024-03-15'), (2, 3, 90, '2024-03-15'),

(3, 1, 78, '2024-03-15'), (4, 3, 96, '2024-03-15');

-- ⑥ 학생별 평균 점수 조회 (GROUP BY 활용)

SELECT s.name AS 학생이름, ROUND(AVG(sc.score),1) AS 평균점수,

COUNT(sc.score_id) AS 시험횟수, MAX(sc.score) AS 최고점

FROM students s

JOIN scores sc ON s.student_id = sc.student_id

GROUP BY s.student_id, s.name

ORDER BY 평균점수 DESC;

12

현업 면접 SQL Q&A + 학습 로드맵

💼 현업 실무 면접 단골 SQL 질문 TOP 8

Q1. DELETE, TRUNCATE, DROP의 차이를 설명하세요.

A: DELETE는 WHERE 조건으로 특정 행을 삭제하며 롤백 가능합니다. TRUNCATE는 테이블 전체 데이터를 빠르게 삭제하지만 롤백이 불가능하고 테이블 구조는 남습니다. DROP은 테이블 자체를 완전히 삭제하며 복구 불가능합니다. 현업에서는 안전을 위해 삭제 전 반드시 SELECT로 대상을 확인하고 트랜잭션을 사용합니다.

Q2. WHERE와 HAVING의 차이를 설명하세요.

A: WHERE는 GROUP BY 이전에 개별 행에 조건을 적용하며 집계 함수를 사용할 수 없습니다. HAVING은 GROUP BY 이후 그룹화된 결과에 조건을 적용하며 AVG(), COUNT() 같은 집계 함수 사용이 가능합니다. "평균 점수가 80점 이상인 과목만"과 같은 조건은 반드시 HAVING을 사용해야 합니다.

Q3. NULL과 빈 문자열("")의 차이는 무엇인가요?

A: NULL은 값이 존재하지 않는 상태(알 수 없음)이고, 빈 문자열은 길이가 0인 문자열 값입니다. NULL은 비교 연산자(=, !=)로 검사 불가능하며 반드시 IS NULL / IS NOT NULL을 사용해야 합니다. 집계 함수에서 COUNT(*)는 NULL 포함 전체 행을 세지만, COUNT(col)은 NULL을 제외하고 셉니다.

Q4. DISTINCT와 GROUP BY의 차이는?

A: DISTINCT는 중복된 행을 제거하여 고유한 값만 반환합니다. GROUP BY는 그룹화 후 집계 함수와 함께 사용하여 통계를 낼 수 있습니다. 단순 중복 제거에는 DISTINCT, 집계 분석에는 GROUP BY를 사용합니다. 대용량 데이터에서는 GROUP BY가 일반적으로 더 빠릅니다.

Q5. UPDATE나 DELETE 시 실수를 방지하는 방법은?

A: ① 먼저 동일한 WHERE 조건으로 SELECT를 실행하여 대상 확인 ② BEGIN(트랜잭션 시작) 후 UPDATE/DELETE 실행 ③ 결과를 확인 후 문제 없으면 COMMIT, 문제 있으면 ROLLBACK ④ 중요 작업 전 백업 수행. 현업에서 WHERE 없는 UPDATE/DELETE는 회사를 잠깐 뒤집어놓을 수 있는 실수입니다.

Q6. 현업에서 SELECT * 를 사용하면 안 되는 이유는?

A: ① 불필요한 컬럼까지 전송하여 네트워크 부하 증가 ② 인덱스를 활용한 커버링 인덱스(covering index) 최적화 불가 ③ 컬럼 추가/삭제 시 예기치 않은 버그 발생 가능 ④ 코드 가독성 저하. 현업에서는 항상 필요한 컬럼만 명시하는 것이 원칙입니다.

Q7. AUTO_INCREMENT로 생성된 ID가 1, 2, 3, 5, 6일 때 4는 왜 없을까요?

A: AUTO_INCREMENT는 한 번 증가하면 롤백되어도 되돌아가지 않습니다. 4번 행이 INSERT 시도 후 트랜잭션 롤백이나 에러로 취소되었을 가능성이 높습니다. 이는 정상적인 동작이며, ID 연속성이 보장되지 않는 것은 AUTO_INCREMENT의 설계 특성입니다. ID 순서에 비즈니스 로직을 의존해서는 안 됩니다.

Q8. SQL 쿼리의 실행 순서는 어떻게 되나요?

A: SQL은 작성 순서(SELECT-FROM-WHERE-GROUP BY-HAVING-ORDER BY-LIMIT)와 실제 실행 순서가 다릅니다. 실행 순서: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT. 이를 이해하면 WHERE에서 집계 함수를 쓸 수 없는 이유, SELECT에서 만든 별칭(AS)을 WHERE에서 사용할 수 없는 이유를 이해할 수 있습니다.

🗺️ 데이터베이스 개발자 학습 로드맵

단계 학습 내용 기간 상태
1단계 DB 개념 이해 - 테이블, 키, ACID, DBMS 비교 (Guide0001) 1~2주 ✅ 완료
2단계 SQL 기초 - SELECT, WHERE, INSERT, UPDATE, DELETE, DDL (Guide0002) 3~4주 📖 현재
3단계 SQL 심화 - JOIN, GROUP BY, 서브쿼리, 인덱스 (Guide0003) 2~3주 ⏳ 예정
4단계 DB 설계 - 정규화, ERD, 쇼핑몰 DB 설계 (Guide0004) 2~3주 ⏳ 예정
5단계 NoSQL 입문 - MongoDB, Redis (Guide0005) 2주 ⏳ 예정
6단계 실전 활용 - 백엔드 연동(ORM), 트랜잭션, 보안 (Guide0006) 2주 ⏳ 예정
7단계 실전 프로젝트 - 블로그/쇼핑몰 DB 전체 설계 및 구현 (Guide0007) 3~4주 ⏳ 예정

🔧 필수 실습 도구

  • MySQL 8.0+ - 관계형 DB 실습 (무료)
  • DBeaver Community - GUI 관리 도구 (무료)
  • DB Fiddle - 온라인 SQL 실습 (설치 불필요)
  • SQLiteOnline.com - 간단한 실습용

📚 추천 학습 자료

  • SQLZoo.net - 인터랙티브 SQL 학습
  • LeetCode SQL - 실전 문제 풀이
  • HackerRank SQL - 단계별 도전 문제
  • W3Schools SQL - 레퍼런스 + 빠른 실습

🎉

수고하셨습니다!

SELECT부터 DDL, GROUP BY까지 SQL 기초를 완전 정복했습니다!
이 내용을 완전히 이해하고 직접 쿼리를 작성할 수 있다면 현업 DB 개발자로서 실력을 갖춘 것입니다.

다음 단계 →

DatabaseDevGuide0003

SQL 심화 - JOIN, 서브쿼리, 인덱스 완전 정복

09

DDL — 테이블 생성·수정·삭제 완전 마스터

💡 DDL(Data Definition Language)이란?

DDL은 데이터베이스 구조(스키마)를 정의하고 수정하는 명령어입니다. 집 짓기로 비유하면 설계도(테이블 구조)를 만들고 수정하는 작업입니다. DDL 명령은 자동 COMMIT됩니다 (롤백 불가!).

🔨 CREATE TABLE — 테이블 생성 상세

-- 가장 완전한 형태의 CREATE TABLE 예시
CREATE TABLE products (
  id           INT             AUTO_INCREMENT PRIMARY KEY,
  name         VARCHAR(200)    NOT NULL                COMMENT '상품명',
  price        DECIMAL(12, 0)  NOT NULL DEFAULT 0     COMMENT '판매가',
  stock        INT             NOT NULL DEFAULT 0     COMMENT '재고수량',
  category     VARCHAR(50),
  description  TEXT,
  is_active    TINYINT(1)      DEFAULT 1             COMMENT '판매 여부',
  created_at   TIMESTAMP       DEFAULT CURRENT_TIMESTAMP,
  updated_at   TIMESTAMP       DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='상품 테이블';

✏️ ALTER TABLE — 테이블 구조 수정

-- 1. 컬럼 추가
ALTER TABLE users
ADD COLUMN phone VARCHAR(20) AFTER email;  -- email 컬럼 뒤에 추가

-- 2. 컬럼 수정 (타입/이름 변경)
ALTER TABLE users
MODIFY COLUMN grade VARCHAR(30) DEFAULT '일반';  -- 길이 변경

-- 3. 컬럼 이름 변경
ALTER TABLE users
RENAME COLUMN grade TO membership_grade;

-- 4. 컬럼 삭제
ALTER TABLE users
DROP COLUMN phone;

-- 5. 테이블 이름 변경
RENAME TABLE users TO members;

-- 6. 인덱스 추가 (검색 성능 향상)
ALTER TABLE users
ADD INDEX idx_email (email);

⚠️ DROP TABLE 주의!

-- 테이블 완전 삭제 (복구 불가!)
DROP TABLE users;

-- 존재할 때만 삭제 (에러 방지)
DROP TABLE IF EXISTS users;

💡 SHOW 명령어 활용

-- DB 목록 조회
SHOW DATABASES;

-- 테이블 목록 조회
SHOW TABLES;

-- 테이블 구조 보기
DESCRIBE users;
10

집계 함수와 GROUP BY — 데이터 통계 분석

💡 집계 함수란?

여러 행의 데이터를 하나로 요약하는 함수입니다. "전체 주문 수", "평균 나이", "최대 금액" 같은 통계 분석에 필수입니다. GROUP BY와 함께 사용하면 그룹별 통계를 낼 수 있습니다.

📊 집계 함수 완전 정리

함수 기능 예시 결과 NULL 처리
COUNT(*) 전체 행 수 COUNT(*) 5 (전체 회원 수) NULL 포함
COUNT(col) NULL 제외한 행 수 COUNT(phone) 전화번호 있는 수 NULL 제외
SUM(col) 합계 SUM(amount) 전체 주문금액 합계 NULL 무시
AVG(col) 평균 AVG(age) 회원 평균 나이 NULL 무시
MAX(col) 최댓값 MAX(amount) 최고 주문금액 NULL 무시
MIN(col) 최솟값 MIN(age) 최연소 회원 나이 NULL 무시

📌 GROUP BY + HAVING 실전 예제

예제 1: 등급별 회원 수와 평균 나이

SELECT
  grade           AS '등급',
  COUNT(*)        AS '회원수',
  AVG(age)        AS '평균나이',
  MIN(age)        AS '최소나이',
  MAX(age)        AS '최대나이'
FROM users
GROUP BY grade
ORDER BY COUNT(*) DESC;
-- 등급별로 묶어서 각종 통계 계산

예제 2: HAVING — 그룹 필터링 (집계 결과에 조건 적용)

-- 주문 수가 2건 이상인 회원의 총 주문금액
SELECT
  user_id,
  COUNT(*) AS '주문건수',
  SUM(amount) AS '총주문금액'
FROM orders
GROUP BY user_id
HAVING COUNT(*) >= 2   -- WHERE는 그룹 전, HAVING은 그룹 후!
ORDER BY '총주문금액' DESC;

💡 WHERE vs HAVING 차이점 (자주 혼동!)

구분 WHERE HAVING
적용 시점 GROUP BY 전 GROUP BY 후
사용 대상 개별 행(Row)에 조건 그룹(집계) 결과에 조건
집계함수 사용 ❌ 불가 ✅ 가능
예시 WHERE age >= 30 HAVING COUNT(*) >= 2

📌 SQL 실행 순서 (매우 중요!)

SQL은 작성 순서와 실행 순서가 다릅니다!

작성 순서

① SELECT
② FROM
③ WHERE
④ GROUP BY
⑤ HAVING
⑥ ORDER BY
⑦ LIMIT

실행 순서

① FROM
② WHERE
③ GROUP BY
④ HAVING
⑤ SELECT
⑥ ORDER BY
⑦ LIMIT

이 순서를 알면 왜 WHERE에서 SELECT의 별칭(AS)을 못 쓰는지, HAVING을 왜 따로 써야 하는지 이해됩니다!

11

실습 프로젝트 - 학생 성적 관리 시스템

🎯 프로젝트 목표

지금까지 배운 SELECT, WHERE, INSERT, UPDATE, DELETE, GROUP BY를 모두 활용하는 실전 프로젝트입니다. 학생 성적 관리 시스템의 DB를 직접 만들고 쿼리를 작성해보세요!

📐 데이터베이스 설계 (ERD 다이어그램)

students

PK: student_id

name, grade, class

birth_date, created_at

1:N
scores

PK: score_id

FK: student_id

subject, score

exam_date

📌 실전 쿼리 요구사항 10문제

번호 요구사항 사용 기술
Q1 전체 학생 목록을 이름 가나다 순으로 조회 SELECT, ORDER BY
Q2 수학 점수가 80점 이상인 학생의 이름과 점수 조회 WHERE, LIKE
Q3 학생별 평균점수, 최고점, 최저점 조회 (높은 순) GROUP BY, AVG, MAX, MIN
Q4 과목별 평균점수와 응시인원 조회 GROUP BY, COUNT, AVG
Q5 평균 점수가 80점 이상인 학생만 조회 GROUP BY, HAVING
Q6 새 학생 '강다현' (3학년 C반) 등록 INSERT INTO
Q7 박지훈의 국어 점수를 80점으로 수정 UPDATE, WHERE
Q8 60점 미만 점수 데이터 전체 조회 WHERE, ORDER BY
Q9 가장 최근 시험 날짜와 가장 오래된 시험 날짜 조회 MAX, MIN
Q10 각 학생의 수학, 영어, 국어 점수를 한 행에 표시 GROUP BY, MAX+CASE (피벗)

정답 예시 (Q3, Q5, Q10)

-- Q3: 학생별 통계
SELECT st.name, ROUND(AVG(sc.score),1) AS avg_score,
       MAX(sc.score) AS max_score, MIN(sc.score) AS min_score
FROM students st JOIN scores sc ON st.student_id = sc.student_id
GROUP BY st.student_id, st.name
ORDER BY avg_score DESC;

-- Q5: 평균 80 이상 학생
SELECT st.name, ROUND(AVG(sc.score),1) AS avg_score
FROM students st JOIN scores sc ON st.student_id = sc.student_id
GROUP BY st.student_id, st.name
HAVING AVG(sc.score) >= 80;

-- Q10: 피벗 테이블 (과목별 열로 전환)
SELECT
  st.name,
  MAX(CASE WHEN sc.subject = '수학' THEN sc.score END) AS math,
  MAX(CASE WHEN sc.subject = '영어' THEN sc.score END) AS english,
  MAX(CASE WHEN sc.subject = '국어' THEN sc.score END) AS korean
FROM students st JOIN scores sc ON st.student_id = sc.student_id
GROUP BY st.student_id, st.name;
12

현업 면접 SQL Q&A + 자주 쓰는 함수 모음

💼 현업 면접 단골 SQL 질문 TOP 8

Q1. SELECT * 와 SELECT 컬럼명 의 차이는?

SELECT *는 모든 컬럼을 가져오므로 편리하지만, 필요 없는 컬럼까지 전송되어 네트워크 낭비와 성능 저하가 발생합니다. 현업에서는 필요한 컬럼만 명시적으로 지정하는 것이 원칙입니다. 또한 SELECT *는 테이블 구조 변경 시 예상치 못한 결과가 나올 수 있습니다.

Q2. WHERE와 HAVING의 차이는?

WHERE는 GROUP BY 이전에 개별 행을 필터링하며 집계 함수를 사용할 수 없습니다. HAVING은 GROUP BY 이후 그룹화된 결과에 조건을 적용하며 COUNT, SUM 같은 집계 함수를 사용합니다. 예: "30세 이상 회원의 등급별 수" → WHERE로 30세 이상 필터 후 GROUP BY, HAVING으로 필요 그룹 추가 필터링.

Q3. NULL과 빈 문자열의 차이와 NULL 처리 방법은?

NULL은 "값이 없음"을 뜻하는 특수 상태이고, 빈 문자열('')은 "길이 0인 문자열"입니다. NULL에 어떤 연산을 해도 NULL이 됩니다 (1 + NULL = NULL). NULL 체크는 반드시 IS NULL / IS NOT NULL을 사용해야 하며, = NULL은 동작하지 않습니다. 함수: COALESCE(col, '기본값'), IFNULL(col, '기본값')으로 NULL을 기본값으로 대체합니다.

Q4. DELETE, TRUNCATE, DROP의 차이는?

DELETE는 WHERE 조건에 맞는 행만 삭제하며 롤백 가능합니다. TRUNCATE는 테이블의 모든 행을 빠르게 삭제(롤백 불가, 테이블 구조 유지). DROP은 테이블 자체를 완전 삭제합니다. 실무에서 실수로 TRUNCATE/DROP하면 데이터 복구가 매우 어려우므로 항상 백업 후 실행해야 합니다.

Q5. AUTO_INCREMENT는 무엇이고 주의사항은?

AUTO_INCREMENT는 INSERT 시 자동으로 1씩 증가하는 고유 번호를 생성합니다. 중요한 점은 한번 증가한 값은 삭제해도 돌아오지 않습니다 (1, 2, 3 삭제 후 다음 INSERT는 4). 따라서 비즈니스 로직에서 ID 연속성에 의존하면 안됩니다. 마지막 삽입 ID는 LAST_INSERT_ID()로 확인 가능합니다.

Q6. 인덱스(Index)란 무엇이고 어디에 걸어야 하나요?

인덱스는 데이터 검색 속도를 높이는 자료구조로, 책의 색인(찾아보기)과 같습니다. PK에는 자동으로 인덱스가 생성됩니다. WHERE 조건에 자주 쓰이는 컬럼, JOIN에 사용되는 FK 컬럼, ORDER BY에 자주 쓰이는 컬럼에 추가하면 효과적입니다. 단, 인덱스가 많으면 INSERT/UPDATE/DELETE 성능이 저하되므로 신중하게 선택해야 합니다.

Q7. UPDATE에서 실수로 WHERE 빠뜨리면 어떻게 되나요? 예방법은?

WHERE 없는 UPDATE/DELETE는 테이블 전체 행에 적용됩니다 (대참사!). 예방법: ① MySQL의 safe_update_mode 활성화 ② UPDATE/DELETE 전에 항상 같은 WHERE로 SELECT 먼저 실행해서 확인 ③ 트랜잭션으로 감싸고 결과 확인 후 COMMIT ④ 변경 전 백업 습관화. SET SQL_SAFE_UPDATES = 1; 명령으로 안전 모드를 켤 수 있습니다.

Q8. SQL 성능 최적화의 기본 원칙을 설명해주세요.

① SELECT *보다 필요한 컬럼만 지정 ② WHERE 조건에 인덱스 컬럼 활용 ③ WHERE 조건에 함수 사용 금지 (WHERE YEAR(created_at) = 2024 대신 BETWEEN 사용) ④ 필요한 만큼만 LIMIT 사용 ⑤ EXPLAIN으로 쿼리 실행 계획 확인 ⑥ N+1 문제 주의 (루프 안에서 쿼리 실행 금지) ⑦ 집계 쿼리는 캐시 또는 별도 통계 테이블 활용.

🔧 현업에서 자주 쓰는 SQL 함수 완전 정리

함수 분류 기능 예시
NOW() 날짜/시간 현재 날짜+시간 SET updated_at = NOW()
DATE(datetime) 날짜/시간 날짜만 추출 DATE(created_at)
YEAR/MONTH/DAY 날짜/시간 년/월/일 추출 YEAR(birth_date) = 2000
CONCAT(a, b) 문자열 문자열 연결 CONCAT(first_name,' ',last_name)
LENGTH(str) 문자열 문자열 바이트 길이 WHERE LENGTH(password) >= 8
SUBSTRING(str,s,l) 문자열 부분 문자열 추출 SUBSTRING(phone, 1, 3)
ROUND(n, d) 수학 반올림 (d자리) ROUND(AVG(score), 1)
FLOOR/CEIL 수학 내림 / 올림 FLOOR(price / 1000)
COALESCE(a,b) NULL 처리 첫 번째 NULL이 아닌 값 COALESCE(phone, '미등록')
IFNULL(a, b) NULL 처리 NULL이면 b 반환 IFNULL(grade, '일반')
CASE WHEN 조건 IF-ELSE처럼 조건별 값 CASE WHEN score >= 90 THEN 'A'

📚 SQL 학습 로드맵 & 다음 단계

🗺️ DatabaseDevGuide 전체 로드맵

단계 학습 내용 기간 상태
1단계 DB 개념 이해 - 테이블, 키, ACID, DBMS 비교 (Guide0001) 1~2주 ✅ 완료
2단계 SQL 기초 - SELECT, WHERE, INSERT, UPDATE, DELETE, GROUP BY (Guide0002 - 현재) 3~4주 ✅ 현재
3단계 SQL 심화 - JOIN, 서브쿼리, 인덱스, 뷰 (Guide0003) 2~3주 ⏳ 예정
4단계 DB 설계 - 정규화, ERD, 쇼핑몰 DB 설계 (Guide0004) 2~3주 ⏳ 예정
5단계 NoSQL 입문 - MongoDB, Redis (Guide0005) 2주 ⏳ 예정
6단계 실전 활용 - 백엔드 연동, ORM, 트랜잭션, 보안 (Guide0006) 2주 ⏳ 예정
7단계 실전 프로젝트 - 블로그/쇼핑몰 DB 전체 설계 및 구현 (Guide0007) 3~4주 ⏳ 예정

📌 SQL 실력 체크리스트 (이 가이드 완성 기준)

✅ 기본 SELECT

  • SELECT, FROM, WHERE 자유롭게 사용
  • ORDER BY, LIMIT으로 정렬/제한
  • DISTINCT로 중복 제거
  • AS로 별칭 지정

✅ 조건 필터링

  • 비교연산자, IN, BETWEEN 활용
  • LIKE 패턴 검색
  • IS NULL / IS NOT NULL
  • AND/OR 복합 조건

✅ 데이터 변경

  • INSERT INTO (단건/다건)
  • UPDATE SET WHERE
  • DELETE FROM WHERE
  • CASE WHEN 조건부 수정

✅ 집계 분석

  • COUNT, SUM, AVG, MAX, MIN
  • GROUP BY 그룹별 통계
  • HAVING 그룹 필터
  • SQL 실행 순서 이해

📚 추천 학습 자료 및 실습 사이트

사이트 특징 추천 대상 비용
SQLZoo 브라우저에서 바로 SQL 실행, 단계별 문제 완전 입문자 무료
HackerRank SQL 난이도별 SQL 문제 풀이, 즉시 채점 입문~중급 무료
LeetCode Database 실제 기업 면접 SQL 문제, 해설 풍부 취업 준비 무료(기본)
Mode Analytics 실제 데이터로 SQL 분석, 데이터 분석가용 데이터 분석가 무료
MySQL 공식 문서 모든 함수, 명령어 레퍼런스 레퍼런스용 무료
🎉

SQL 기초 완전 정복 완료!

SELECT, WHERE, ORDER BY, INSERT, UPDATE, DELETE, GROUP BY, DDL까지
모두 마스터했습니다! 이제 기본적인 DB 작업은 모두 할 수 있습니다.

📌 다음 단계: DatabaseDevGuide0003

SQL 심화 - JOIN(테이블 조인), 서브쿼리, 인덱스 전략, 뷰(View)

✅ SELECT 마스터 ✅ DML 완전 습득 ✅ DDL 기초 완성 ✅ 실습 프로젝트 완료
반응형