어제는 MySQL의 기본 명령어를 공부하면서
SELECT, WHERE, ORDER BY,
LIMIT 등의 기본적인 사용 방법을 정리했습니다.
오늘은 여기에서 한 단계 더 나아가 데이터를 계산하고, 그룹으로 묶고, 조건을 적용하고, 문자열과 날짜를 가공하고, 여러 테이블을 연결하는 방법을 배웠습니다.
처음 보면 명령어가 갑자기 많아진 것처럼 느껴집니다. 그래서 이번 글에서는 단순히 명령어를 나열하지 않고 “이런 결과가 필요하면 어떤 문법을 떠올려야 할까?” 라는 초보자 관점에서 정리해 보겠습니다.
1. 오늘 배운 내용을 먼저 한눈에 보기
| 분류 | 오늘 배운 문법 |
|---|---|
| 집계 | COUNT(), SUM(), AVG(), MAX(), MIN() |
| 그룹화 | GROUP BY |
| 그룹 조건 | HAVING |
| 조건부 데이터 | INSERT IGNORE, ON DUPLICATE KEY UPDATE |
| 데이터 타입 | INT, BIGINT, FLOAT, DOUBLE, DECIMAL, VARCHAR, TEXT, DATE, DATETIME 등 |
| 사용자 변수 | @변수 |
| 형변환 | CAST(), CONVERT() |
| 문자열 | CONCAT(), SUBSTRING(), LENGTH(), LOWER(), UPPER(), REPLACE() |
| 날짜/시간 | NOW(), CURDATE(), CURTIME(), DATEDIFF(), DATE_ADD(), DATE_FORMAT() |
| 조건 처리 | IF(), IFNULL(), CASE |
| 테이블 연결 | INNER JOIN, LEFT/RIGHT OUTER JOIN, CROSS JOIN, SELF JOIN |
2. 집계 함수부터 이해하기
집계 함수는 여러 행의 데이터를 가지고 하나의 결과를 계산할 때 사용하는 함수입니다.
COUNT()→ 개수SUM()→ 합계AVG()→ 평균MAX()→ 최대값MIN()→ 최소값
예를 들어 상품 테이블에 상품이 100개 있다면
“상품이 총 몇 개인가?”라는 질문에
COUNT()를 사용할 수 있습니다.
문제 1. 전체 회원 수 확인하기
회원 테이블에 등록된 회원이 모두 몇 명인지 확인합니다.
연상하기
여러 행의 개수를 세어야 합니다.
SELECTCOUNT()FROM
정답 확인하기
SELECT COUNT(*) FROM member;
문제 2. 상품 가격의 합계 구하기
상품 테이블에 등록된 상품 가격을 모두 더한 금액을 확인합니다.
연상하기
SUM()- 계산할 컬럼명
FROM
정답 확인하기
SELECT SUM(price) FROM product;
SUM()을 사용합니다.
문제 3. 평균 가격 구하기
등록된 상품의 평균 가격을 확인합니다.
연상하기
AVG()- 평균을 계산할 컬럼
정답 확인하기
SELECT AVG(price) FROM product;
AVG()로 계산합니다.
문제 4. 가장 비싼 상품과 가장 저렴한 상품 찾기
상품 가격 중 가장 높은 가격과 가장 낮은 가격을 각각 확인합니다.
연상하기
MAX()MIN()- 가격 컬럼
정답 확인하기
SELECT
MAX(price) AS max_price,
MIN(price) AS min_price
FROM product;
MAX(), 최소값은 MIN()입니다.
3. GROUP BY로 데이터를 묶어보기
COUNT()나 SUM()을 사용하면
전체 데이터에 대한 계산을 할 수 있습니다.
그런데 실제 업무에서는 “상품 종류별로 몇 개인가?”, “부서별 평균 급여는 얼마인가?” 처럼 그룹별 계산을 해야 하는 경우가 많습니다.
이때 사용하는 것이 GROUP BY입니다.
문제 5. 카테고리별 상품 개수 구하기
상품을 카테고리별로 묶어서 각 카테고리에 상품이 몇 개씩 등록되어 있는지 확인합니다.
연상하기
COUNT()GROUP BY- 그룹으로 묶을 컬럼
정답 확인하기
SELECT category, COUNT(*) FROM product GROUP BY category;
GROUP BY는 같은 값을 가진 데이터를 그룹으로 묶어줍니다.
4. WHERE와 HAVING의 차이 생각하기
오늘 공부하면서 헷갈리기 쉬운 부분이
WHERE와 HAVING입니다.
간단하게 기억하면,
WHERE→ 개별 행을 먼저 조건으로 걸러냄HAVING→ GROUP BY로 만들어진 그룹에 조건을 적용
즉, “데이터를 먼저 걸러내느냐, 그룹을 만든 후 걸러내느냐” 를 생각하면 됩니다.
문제 6. 상품이 5개 이상인 카테고리만 조회하기
카테고리별 상품 개수를 계산한 후 상품이 5개 이상인 카테고리만 확인합니다.
연상하기
COUNT()GROUP BY- 그룹 결과에 조건 적용
HAVING
정답 확인하기
SELECT category, COUNT(*) FROM product GROUP BY category HAVING COUNT(*) >= 5;
HAVING을 사용합니다.
5. 중복 데이터를 처리하는 방법
데이터를 입력하다 보면 이미 존재하는 PRIMARY KEY가 다시 입력되는 경우가 있습니다.
오늘은 이런 상황에서 사용할 수 있는 두 가지 문법을 배웠습니다.
INSERT IGNOREON DUPLICATE KEY UPDATE
문제 7. 중복 오류를 무시하고 데이터 입력하기
기존 PK와 중복되는 데이터가 입력되더라도 오류를 발생시키지 않고 해당 행의 삽입을 건너뜁니다.
연상하기
INSERT IGNOREINTOVALUES
정답 확인하기
INSERT IGNORE INTO member (member_id, name) VALUES (101, '김민수');
문제 8. 중복이면 UPDATE하기
회원 번호가 이미 존재하지 않으면 데이터를 INSERT하고, 이미 존재하면 이름을 UPDATE합니다.
연상하기
INSERT INTOVALUESON DUPLICATE KEY UPDATE
정답 확인하기
INSERT INTO member (member_id, name) VALUES (101, '김민수') ON DUPLICATE KEY UPDATE name = '김민수';
6. 데이터 타입 이해하기
테이블을 만들 때는 컬럼에 어떤 종류의 데이터를 저장할 것인지 정해야 합니다.
| 종류 | 주요 타입 |
|---|---|
| 정수형 | SMALLINT, INT, BIGINT |
| 실수형 | FLOAT, DOUBLE, DECIMAL |
| 문자형 | CHAR(N), VARCHAR(N), TEXT, LONGTEXT |
| 날짜/시간형 | DATE, TIME, DATETIME |
예를 들어 가격처럼 정확한 숫자를 저장해야 하는 경우에는
상황에 따라 DECIMAL을 사용할 수 있습니다.
7. 사용자 정의 변수 @변수
MySQL에서는 @변수명 형태로 사용자 정의 변수를 사용할 수 있습니다.
처음에는 어렵게 생각하지 말고 “값을 잠시 담아두는 이름”이라고 생각하면 됩니다.
문제 9. 변수에 값을 저장하고 사용하기
숫자 5000을 변수에 저장한 후 그 값을 조회합니다.
연상하기
@변수SETSELECT
정답 확인하기
SET @price = 5000; SELECT @price;
@price라는 사용자 정의 변수에 값을 저장했습니다.
8. 형변환 CAST와 CONVERT
데이터를 다루다 보면 숫자를 문자열처럼 사용하거나 문자열을 숫자 형태로 변환해야 하는 경우가 있습니다.
이때 사용하는 것이 형변환입니다.
CAST(값 AS 데이터타입)CONVERT(값, 데이터타입)
문제 10. 숫자를 문자 형태로 변환하기
숫자 2026을 문자 형태로 변환하여 확인합니다.
연상하기
- 형변환
CAST()ASCHAR
정답 확인하기
SELECT CAST(2026 AS CHAR);
CAST()는 지정한 데이터 타입으로 값을 변환합니다.
9. 문자열 함수 사용하기
오늘 배운 문자열 함수는 데이터를 보기 좋은 형태로 만들거나 필요한 부분만 추출할 때 활용할 수 있습니다.
CONCAT()→ 문자열 연결SUBSTRING()→ 문자열 일부 추출LENGTH()→ 문자열의 바이트 수LOWER()/UPPER()→ 대소문자 변환REPLACE()→ 문자열 치환
문제 11. 이름과 등급을 하나의 문자열로 만들기
회원의 이름과 등급을 하나의 문자열로 연결합니다.
예를 들어 다음과 같은 형태입니다.
김민수 - GOLD
연상하기
CONCAT()- 문자열 연결
- 컬럼과 문자열을 함께 사용
정답 확인하기
SELECT CONCAT(name, ' - ', grade) FROM member;
CONCAT()을 사용합니다.
문제 12. 상품명 일부만 추출하기
상품명의 첫 번째 문자부터 세 글자만 추출합니다.
연상하기
SUBSTRING()- 문자열
- 시작 위치
- 추출할 길이
정답 확인하기
SELECT SUBSTRING(product_name, 1, 3) FROM product;
SUBSTRING(문자열, 시작위치, 길이)
형태로 문자열 일부를 추출할 수 있습니다.
10. 날짜와 시간 함수
날짜와 시간 데이터도 SQL에서는 자주 다루게 됩니다.
NOW()→ 현재 날짜와 시간CURDATE()→ 현재 날짜CURTIME()→ 현재 시간DATEDIFF()→ 날짜 사이의 일수 차이DATE_ADD()→ 날짜에 기간 더하기DATE_FORMAT()→ 날짜 형식 변경
문제 13. 현재 날짜와 시간 확인하기
현재 날짜와 시간을 확인합니다.
연상하기
SELECTNOW()
정답 확인하기
SELECT NOW();
NOW()를 사용합니다.
문제 14. 두 날짜 사이의 기간 계산하기
2026년 9월 1일부터 2026년 9월 16일까지 며칠 차이가 나는지 계산합니다.
연상하기
DATEDIFF()- 첫 번째 날짜
- 두 번째 날짜
정답 확인하기
SELECT DATEDIFF('2026-09-16', '2026-09-01');
DATEDIFF(date1, date2)는 두 날짜의 일수 차이를 계산합니다.
11. IF와 IFNULL
조건에 따라 다른 결과를 표시하거나 NULL 값을 다른 값으로 바꾸어 표시할 수도 있습니다.
IF(조건식, 참, 거짓)IFNULL(검사할 값, 대체 값)
문제 15. 가격에 따라 상품 상태 표시하기
상품 가격이 10000원 이상이면 “고가”, 그렇지 않으면 “일반”이라고 표시합니다.
연상하기
IF()- 조건식
- 참일 때 결과
- 거짓일 때 결과
정답 확인하기
SELECT
product_name,
price,
IF(price >= 10000, '고가', '일반') AS price_type
FROM product;
IF()를 사용해 간단하게 표현할 수 있습니다.
12. CASE 구문
조건이 하나가 아니라 여러 개라면
CASE 구문을 사용할 수 있습니다.
기본적인 형태는 다음과 같습니다.
CASE
WHEN 조건식1 THEN 결과1
WHEN 조건식2 THEN 결과2
ELSE 그 외의 결과
END
문제 16. 가격에 따라 상품 등급 나누기
상품 가격에 따라 다음과 같이 구분합니다.
- 20000원 이상 → PREMIUM
- 10000원 이상 → STANDARD
- 그 외 → BASIC
연상하기
CASEWHENTHENELSEEND
정답 확인하기
SELECT
product_name,
price,
CASE
WHEN price >= 20000 THEN 'PREMIUM'
WHEN price >= 10000 THEN 'STANDARD'
ELSE 'BASIC'
END AS product_grade
FROM product;
CASE를 사용할 수 있습니다.
13. JOIN으로 두 테이블 연결하기
지금까지는 하나의 테이블을 기준으로 데이터를 조회했습니다.
하지만 실제 데이터베이스에서는 회원 정보, 주문 정보, 상품 정보 등이 여러 테이블로 나누어져 있는 경우가 많습니다.
이때 서로 관련된 테이블을 연결하는 것이 JOIN입니다.
오늘 배운 JOIN은 다음과 같습니다.
INNER JOINLEFT OUTER JOINRIGHT OUTER JOINCROSS JOINSELF JOIN
문제 17. 주문과 회원 정보 연결하기
주문 테이블의 회원 ID와 회원 테이블의 회원 ID를 연결하여 회원 이름과 주문 금액을 함께 조회합니다.
연상하기
SELECT- 두 테이블의 컬럼
FROMINNER JOINON- 두 테이블의 연결 키
정답 확인하기
SELECT
M.name,
O.order_price
FROM member AS M
INNER JOIN orders AS O
ON M.member_id = O.member_id;
INNER JOIN은 두 테이블의 연결 조건을 만족하는 데이터를 조회합니다.
14. 오늘 배운 내용을 하나의 흐름으로 연결하기
오늘 배운 명령어는 각각 따로 떨어져 있는 것이 아닙니다.
예를 들어 실제 업무에서
“회원별 주문 건수를 구하고, 주문이 3건 이상인 회원만 조회한다.”
라는 요구사항이 나온다면
- 회원과 주문 테이블을 연결 →
JOIN - 회원별로 묶기 →
GROUP BY - 주문 개수 계산 →
COUNT() - 3건 이상만 선택 →
HAVING
처럼 여러 문법을 조합하게 됩니다.
처음부터 SQL 전체를 외우려고 하기보다는 문제의 요구사항을 읽고 필요한 문법을 하나씩 연결하는 연습이 중요하다는 생각이 들었습니다.
오늘 배운 MySQL 핵심 명령어 정리
| 하고 싶은 일 | 문법 |
|---|---|
| 데이터 개수 | COUNT() |
| 합계 | SUM() |
| 평균 | AVG() |
| 최대값 | MAX() |
| 최소값 | MIN() |
| 그룹으로 묶기 | GROUP BY |
| 그룹 결과에 조건 적용 | HAVING |
| 중복 입력 무시 | INSERT IGNORE |
| 중복이면 수정 | ON DUPLICATE KEY UPDATE |
| 사용자 변수 | @변수 |
| 형변환 | CAST(), CONVERT() |
| 문자열 연결 | CONCAT() |
| 문자열 추출 | SUBSTRING() |
| 문자열 길이 | LENGTH() |
| 문자열 대소문자 변환 | LOWER(), UPPER() |
| 문자열 치환 | REPLACE() |
| 현재 날짜/시간 | NOW() |
| 현재 날짜 | CURDATE() |
| 현재 시간 | CURTIME() |
| 날짜 차이 | DATEDIFF() |
| 날짜 더하기 | DATE_ADD() |
| 날짜 형식 변경 | DATE_FORMAT() |
| 간단한 조건 | IF() |
| NULL 대체 | IFNULL() |
| 여러 조건 처리 | CASE |
| 두 테이블 연결 | JOIN |
마무리|2일차 공부를 마치며
오늘은 어제보다 확실히 어려워졌습니다.
특히 GROUP BY, HAVING,
형변환, 날짜 함수, CASE,
그리고 JOIN까지 등장하면서
SQL이 단순한 데이터 조회 명령어가 아니라
데이터를 가공하고 분석하는 도구라는 느낌이 들었습니다.
아직은 모든 문법을 외우지는 못했지만, 각 문법이 어떤 상황에서 필요한지 연결하는 것부터 연습해 보려고 합니다.
앞으로 SQL 문제를 볼 때도
① 무엇을 구해야 하는가 → ② 데이터를 어떻게 묶어야 하는가 → ③ 어떤 조건을 적용해야 하는가 → ④ 필요한 테이블을 어떻게 연결하는가
순서로 생각해 보는 연습을 계속해 보겠습니다.
어제 글과 함께 공부하기
MySQL 기본 명령어가 아직 익숙하지 않다면 어제 정리한 기본 명령어부터 다시 확인한 후 오늘 내용을 보는 것도 좋습니다.
MySQL 기본 명령어 정리|정의·문법·예시 한눈에 보기
※ 이 글은 2026년 9월 16일 MySQL 교육에서 학습한 내용을 초보자 관점에서 다시 정리한 개인 학습 기록입니다.
강의에서 배운 명령어를 중심으로 정리했으며, 실제 데이터베이스 환경에서는 테이블 구조와 데이터에 따라 SQL 문법을 다르게 조합할 수 있습니다.
COUNT(*)를 사용할 수 있습니다.