[ECTION06. 샘플 데이터 입력 실습]
CREATE TABLE MEMBER (
member_id BIGINT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
password VARCHAR(255) NOT NULL,
email VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
);
CREATE TABLE CATEGORY (
category_id BIGINT AUTO_INCREMENT PRIMARY KEY,
category_name VARCHAR(50) NOT NULL
);
CREATE TABLE BOARD (
board_id BIGINT AUTO_INCREMENT PRIMARY KEY,
member_id BIGINT NOT NULL,
category_id BIGINT NOT NULL,
title VARCHAR(200) NOT NULL,
content TEXT NOT NULL,
view_count INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
FOREIGN KEY (member_id) REFERENCES MEMBER (member_id),
FOREIGN KEY (category_id) REFERENCES CATEGORY (category_id)
);
CREATE TABLE COMMENTS (
comment_id BIGINT AUTO_INCREMENT PRIMARY KEY,
board_id BIGINT NOT NULL,
member_id BIGINT NOT NULL,
content TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
FOREIGN KEY (board_id) REFERENCES BOARD (board_id),
FOREIGN KEY (member_id) REFERENCES MEMBER (member_id)
);
CREATE TABLE BOARD_LIKE (
board_id BIGINT NOT NULL,
member_id BIGINT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
PRIMARY KEY (board_id, member_id),
FOREIGN KEY (board_id) REFERENCES BOARD (board_id),
FOREIGN KEY (member_id) REFERENCES MEMBER (member_id)
);
SECTION04에서 배운 대로, 참조되는 테이블(부모)을 먼저 채워야 합니다.
1. member (회원)
2. category (카테고리)
3. board (게시글) — member, category를 참조
4. comment (댓글) — board, member를 참조
5. board_like (좋아요) — board, member를 참조
INSERT INTO member (username, email, password) VALUES
('홍길동', 'hong@test.com', '1234'),
('김철수', 'kim@test.com', '1234'),
('이영희', 'lee@test.com', '1234'),
('박민수', 'park@test.com', '1234'),
('정수진', 'jung@test.com', '1234'),
('최동혁', 'choi@test.com', '1234'),
('강지훈', 'kang@test.com', '1234'),
('윤서연', 'yoon@test.com', '1234'),
('한가람', 'han@test.com', '1234'),
('오세훈', 'oh@test.com', '1234');
10명의 회원을 한 번에 등록했습니다. 등록 확인:
SELECT * FROM member;
INSERT INTO category (category_name) VALUES
('자유게시판'),
('공지사항'),
('질문과답변'),
('정보공유');
회원 10명, 카테고리 4개를 다양하게 섞어서 게시글 20건을 등록합니다. member_id는 1~10, category_id는 1~4 범위에서 섞어서 작성합니다.
INSERT INTO board (title, content, member_id, category_id) VALUES
('첫 방문 인사드립니다', '안녕하세요 잘 부탁드립니다', 1, 1),
('이번 주 점검 안내', '서버 점검이 있습니다', 2, 2),
('스프링 질문있습니다', 'JPA 연관관계가 헷갈려요', 3, 3),
('맛집 추천해주세요', '강남역 근처 맛집 추천 부탁드려요', 4, 1),
('자바 스터디 모집', '같이 스터디 하실분 구합니다', 5, 4),
('공지: 이용규칙 안내', '커뮤니티 이용규칙입니다', 1, 2),
('취업 후기 공유', '국비 과정 듣고 취업했습니다', 6, 4),
('알고리즘 공부 방법', '코딩테스트 어떻게 준비하셨나요', 7, 3),
('주말에 등산 가요', '같이 등산 가실분 구합니다', 8, 1),
('리액트 vs 뷰', '둘중에 뭐가 더 배우기 좋을까요', 9, 3),
('점심 메뉴 추천', '오늘 점심 뭐 먹을지 고민이에요', 10, 1),
('공지: 휴일 안내', '다음주 월요일은 휴일입니다', 2, 2),
('포트폴리오 피드백 부탁드려요', '깃허브 링크 첨부합니다', 3, 4),
('자취 꿀팁 공유', '자취 초보를 위한 팁입니다', 4, 4),
('스프링 시큐리티 질문', 'JWT 적용이 잘 안돼요', 5, 3),
('운동 같이 하실분', '러닝 같이 하실분 구해요', 6, 1),
('공지: 신규 기능 추가', '댓글 기능이 추가되었습니다', 1, 2),
('이력서 첨삭 후기', '도움 많이 받았습니다', 7, 4),
('주식 스터디 모집', '같이 공부하실분 구합니다', 8, 4),
('카페 추천 받습니다', '조용한 카페 찾고 있어요', 9, 1);
게시글마다 0~3개씩 댓글을 다양하게 채웁니다. 모든 게시글에 댓글이 있을 필요는 없습니다. (추후 LEFT JOIN 연습할 때 의미가 있는 부분입니다.)
INSERT INTO comments (content, board_id, member_id) VALUES
('환영합니다!', 1, 2),
('반갑습니다', 1, 3),
('확인했습니다', 2, 1),
('저도 같은 질문이 있었어요', 3, 4),
('영한아이로 강추합니다', 4, 5),
('저도 참여하고 싶어요', 5, 6),
('잘 읽었습니다', 6, 2),
('취업 축하드려요!', 7, 1),
('좋은 정보 감사합니다', 8, 9),
('저도 가고싶어요', 9, 10),
('저는 리액트 추천이요', 10, 1),
('잘 챙겨먹을게요', 11, 3),
('확인했습니다', 12, 5),
('포트폴리오 좋네요', 13, 6),
('도움이 많이 됐어요', 14, 7),
('해결되셨나요?', 15, 8),
('저도 참여할게요', 16, 9),
('기대됩니다', 17, 10),
('축하드려요', 18, 4);
같은 회원이 같은 게시글에 두 번 좋아요를 누르지 않도록 조합이 중복되지 않게 작성합니다.
INSERT INTO board_like (board_id, member_id) VALUES
(1, 2), (1, 3), (1, 4),
(2, 1), (2, 5),
(3, 6), (3, 7), (3, 8),
(4, 1), (4, 9),
(5, 2), (5, 3),
(6, 4), (6, 5), (6, 6),
(7, 1), (7, 2), (7, 3), (7, 4),
(8, 9),
(9, 1), (9, 10);
SELECT COUNT(*) FROM member;
SELECT COUNT(*) FROM category;
SELECT COUNT(*) FROM board;
SELECT COUNT(*) FROM comments;
SELECT COUNT(*) FROM board_like;
각각 10, 4, 20, 19, 22건이 나와야 정상입니다. 만약 중간에 FK 에러가 나서 일부만 입력됐다면, SELECT * FROM 테이블명;으로 직접 확인하면서 빠진 부분을 다시 채워 넣습니다.
1. member 테이블에 이름 '서지우', 이메일 'seo@test.com', 비밀번호 '1234'인 회원 1명을 추가하는 SQL을 작성하시오.
insert into member (username, email, password) values ('서지우', 'seo@test.com', '1234');
2. category 테이블에 '취업정보', '스터디모집' 2개를 한 번의 INSERT 문으로 추가하는 SQL을 작성하시오.
insert into category (category_name) values('취업정보'), ('스터디모집')
3. board 테이블에 member_id=11(방금 추가한 서지우), category_id=1로 제목 '안녕하세요 신입입니다', 내용 '잘 부탁드립니다'인 게시글을 추가하는 SQL을 작성하시오.
insert into board (title, content, member_id, category_id) values('안녕하세요 신입입니다', '잘 부탁드립니다', 11, 1)
4. comment 테이블에 board_id=20, member_id=11로 내용 '잘 보고 갑니다'인 댓글 1개를 추가하는 SQL을 작성하시오.
insert into comments (content, board_id, member_id) values ('잘 보고 갑니다', 20, 1)
5. 현재 board 테이블에 총 몇 건의 게시글이 있는지 확인하는 SQL을 작성하시오.
select count(*) from board;
6. board_id가 5인 게시글에 member_id=11이 좋아요를 누르는 SQL을 작성하시오. (단, 이미 좋아요를 눌렀다면 에러가 나야 한다.)
insert into board_like (board_id, member_id) values (5, 11);
[SECTION07. SELECT 기본 — WHERE, ORDER BY, LIKE]
SELECT 컬럼1, 컬럼2 FROM 테이블명;
-- 전체 컬럼 조회
SELECT * FROM board;
-- 원하는 컬럼만 조회
SELECT title, view_count FROM board;
| 연산자 | 의미 |
|---|---|
| = | 같다 |
| != 또는 <> | 다르다 |
| > , < | 크다, 작다 |
| >= , <= | 크거나 같다, 작거나 같다 |
-- member_id가 1인 게시글만 조회
SELECT * FROM board WHERE member_id = 1;
-- 조회수가 0보다 큰 게시글만 조회
SELECT * FROM board WHERE view_count > 0;
-- category_id가 1이면서 member_id가 1인 게시글
SELECT * FROM board WHERE category_id = 1 AND member_id = 1;
-- category_id가 1이거나 2인 게시글
SELECT * FROM board WHERE category_id = 1 OR category_id = 2;
-- category_id가 2가 아닌 게시글
SELECT * FROM board WHERE NOT category_id = 2;
-- member_id가 3부터 6 사이인 게시글 (3, 4, 5, 6 포함)
SELECT * FROM board WHERE member_id BETWEEN 3 AND 6;
-- 게시글 11번에서 20번 조회하는 예제 -> 두번째 페이지
select * from board where board_id between 11 and 20
-- category_id가 1 또는 3 또는 4인 게시글
SELECT * FROM board WHERE category_id IN (1, 3, 4);
OR을 여러 번 쓰는 것보다 IN을 쓰면 훨씬 간결합니다.
-- 아래 두 쿼리는 결과가 동일함
SELECT * FROM board WHERE category_id = 1 OR category_id = 3 OR category_id = 4;
SELECT * FROM board WHERE category_id IN (1, 3, 4);
-- description 컬럼이 비어있는 행 (NULL인 행)
SELECT * FROM board WHERE content IS NULL;
-- 비어있지 않은 행
SELECT * FROM board WHERE content IS NOT NULL;
NULL은
= NULL로 비교할 수 없습니다. 반드시IS NULL/IS NOT NULL을 사용해야 합니다.
| 기호 | 의미 |
|---|---|
| % | 0개 이상의 모든 문자 |
| _ | 정확히 1개의 문자 |
-- 제목에 '공지'가 포함된 게시글
SELECT * FROM board WHERE title LIKE '%공지%';
-- '공지'로 시작하는 게시글
SELECT * FROM board WHERE title LIKE '공지%';
-- '요'로 끝나는 게시글
SELECT * FROM board WHERE title LIKE '%요';
게시판의 “검색” 기능이 바로 이 LIKE를 사용합니다.
-- 제목 또는 내용에 '스프링'이 포함된 게시글 검색
SELECT * FROM board WHERE title LIKE '%스프링%' OR content LIKE '%스프링%';
-- 조회수가 높은 순서로 정렬 (내림차순)
SELECT * FROM board ORDER BY view_count DESC;
-- 작성일이 오래된 순서로 정렬 (오름차순이 기본값[PK])
SELECT * FROM board ORDER BY created_at ASC;
-- 조회수 수정
update board set view_count = 6 where board_id in (5, 6, 10)
-- 조회수를 기준으로 내림차순 정렬을 하면서 그 중에서도 최신글 순으로 정렬
select * from board order by view_count desc, board_id desc
| 키워드 | 의미 |
|---|---|
| ASC | 오름차순 (작은 값 → 큰 값), 기본값 |
| DESC | 내림차순 (큰 값 → 작은 값) |
-- category_id로 먼저 묶고, 같은 카테고리 안에서는 조회수 높은 순
SELECT * FROM board ORDER BY category_id ASC, view_count DESC;
-- 자유게시판(category_id=1)에서 제목에 '추천'이 들어간 게시글을,
-- 조회수가 높은 순서로 정렬해서 조회
SELECT * FROM board
WHERE category_id = 1 AND title LIKE '%추천%'
ORDER BY view_count DESC;
실무 게시판의 “카테고리별 검색 + 정렬” 기능이 바로 이런 형태의 쿼리로 구현됩니다.
-- 가장 최근에 작성된 게시글 5개만 조회
SELECT * FROM board ORDER BY created_at DESC LIMIT 5;
-- 최신 글 중 10개 건너 띄고 그 다음 10개 가져오기 (두 번째 페이지 가져오기)
SELECT * FROM BOARD
ORDER BY board_id DESC
LIMIT 10 OFFSET 10;
페이징(다음 단계에서 다룰 예정)의 기본 원리가 바로 이 LIMIT입니다.
1. board 테이블에서 category_id가 2(공지사항)인 게시글만 조회하는 SQL을 작성하시오.
SELECT * FROM BOARD where category_id = 2
2. board 테이블에서 view_count가 0보다 큰 게시글을, 조회수가 높은 순서로 정렬해서 조회하는 SQL을 작성하시오.
SELECT * FROM BOARD where view_count > 0 order by view_count desc
3. member 테이블에서 이메일이 'test.com'으로 끝나는 회원을 모두 조회하는 SQL을 작성하라.
SELECT * FROM member where email like '%test.com'
4. board 테이블에서 제목에 '공지'가 포함되거나 제목에 '질문'이 포함된 게시글을, 작성일이 최신인 순서로 조회하는 SQL을 작성하라.
SELECT * FROM board where title like '%공지%' or title like '%질문%'
order by created_at desc
5. board 테이블에서 member_id가 1, 3, 5 중 하나인 게시글을 IN을 사용해서 조회하는 SQL을 작성하시오.
SELECT * FROM board where member_id in (1, 3, 5);
6. board 테이블에서 category_id가 1이면서 view_count가 0인(아직 조회수가 없는) 게시글을 조회하는 SQL을 작성하시오.
SELECT * FROM board where category_id = 1 and view_count = 0
7. board 테이블에서 가장 최근에 작성된 게시글 3개만 조회하는 SQL을 작성하시오.
SELECT * FROM board
order by board_id desc limit 3
8. board 테이블에서 category_id 순으로 먼저 정렬하고, 같은 카테고리 안에서는 제목 가나다순(오름차순)으로 정렬하는 SQL을 작성하시오.
SELECT * FROM board
order by category_id, title;
[SECTION08. 조건 검색 쿼리 실습]
실무 게시판에는 보통 “제목”, “내용”, “제목+내용” 검색 옵션이 있습니다.
-- 제목에 '스프링'이 포함된 게시글 검색
SELECT * FROM board WHERE title LIKE '%스프링%';
-- 제목 또는 내용에 '추천'이 포함된 게시글 검색 (통합검색)
SELECT * FROM board WHERE title LIKE '%추천%' OR content LIKE '%추천%';
실무에서는 검색 옵션(제목 / 내용 / 제목과 내용 등)에 따라 WHERE 조건을 동적으로 바꿔야 합니다. 이 부분은 추후 MyBatis 단계에서 동적 SQL(
<if>태그)로 구현하게 됩니다. 지금은 SQL 자체를 손으로 짜는 데 집중합니다.
-- '홍길동'이 쓴 글 찾기 (member 테이블과 직접 연결 전이므로, member_id를 먼저 확인)
SELECT id FROM member WHERE username = '홍길동';
-- 결과로 나온 id(예: 1)를 활용
SELECT * FROM board WHERE member_id = 1;
-- 위 두 쿼리를 합침
select * from board where member_id = (select member_id from member where username = '홍길동')
-- 자유게시판(category_id=1)이면서 조회수가 0보다 큰 글
SELECT * FROM board WHERE category_id = 1 AND view_count > 0;
추후 JOIN을 배우면
member.name으로 직접 검색할 수 있게 됩니다. 지금은 id로 한 단계씩 연결해보는 연습입니다.
-- 오늘 날짜 확인
SELECT CURRENT_DATE;
-- 최근 7일 이내에 작성된 게시글
SELECT * FROM board WHERE created_at >= CURRENT_DATE - 7;
-- 특정 기간 사이에 작성된 게시글 (예: 2026-06-01 ~ 2026-06-30)
SELECT * FROM board WHERE created_at BETWEEN '2026-06-01' AND '2026-06-30 23:59:59';
created_at은 TIMESTAMP(날짜+시간)이기 때문에, 날짜만 적으면00:00:00으로 처리됩니다. 그 날의 마지막 순간까지 포함하려면23:59:59까지 명시하는 것이 안전합니다.
-- 조회수가 높은 게시글 TOP 5
SELECT * FROM board ORDER BY view_count DESC LIMIT 5;
-- 최신글 기준으로 6~10번째 게시글 (페이지 2, 페이지당 5개라고 가정)
SELECT * FROM board ORDER BY created_at DESC LIMIT 5 OFFSET 5;
LIMIT 개수 OFFSET 건너뛸개수를 조합하면 페이지네이션의 기본 형태를 만들 수 있습니다. (정식 페이징은 추후 단계에서 다룹니다.)
JOIN을 아직 배우지 않았지만, 서브쿼리로 간단히 흉내내볼 수 있습니다.
-- 좋아요를 3번 이상 받은 게시글의 id 목록
select board_id, count(*) from board_like group by board_id having count(*) > 3
-- 위 결과를 활용해서 해당 게시글 정보 조회
SELECT * FROM board
WHERE board_id IN (
SELECT board_id FROM board_like GROUP BY board_id HAVING COUNT(*) >= 3
);
GROUP BY와 HAVING은 다음
SECTION(집계함수)에서 자세히 다룹니다.
지금까지 배운 모든 조건을 조합한 예시입니다.
-- 자유게시판(category_id=1) 또는 정보공유(category_id=4)에서,
-- 제목에 '추천'이 포함되고, 조회수가 0 이상이며,
-- 조회수 높은 순 → 최신순으로 정렬해서 상위 10개 조회
SELECT * FROM board
WHERE category_id IN (1, 4)
AND title LIKE '%추천%'
AND view_count >= 0
ORDER BY view_count DESC, created_at DESC
LIMIT 10;
1. board 테이블에서 제목에 '질문'이 포함된 게시글을 조회수 높은 순으로 정렬하는 SQL을 작성하시오.
select * from board where title like '%질문%' order by view_count desc
2. member 테이블에서 이름이 '김철수'인 회원의 id를 조회하는 SQL을 작성하시오. (id가 2라고 가정하고 다음 문제에 활용)
SELECT member_id FROM MEMBER where username = '김철수'
3. 위에서 찾은 member_id(2)가 작성한 게시글을 모두, 최신순으로 조회하는 SQL을 작성하시오.
select * from board where member_id = (SELECT member_id FROM MEMBER where username = '김철수') order by created_at desc;
4. board 테이블에서 category_id가 1 또는 3이면서, 제목 또는 내용에 '스프링'이 포함된 게시글을 조회하는 SQL을 작성하시오.
select * from board
where category_id in (1, 3) and title like '%스프링%' or content like '%스프링%'
5. board 테이블에서 조회수가 가장 낮은 게시글부터 5개를 조회하는 SQL을 작성하시오.
select * from board order by view_count limit 5
6. board 테이블에서 최신글 기준으로 11번째~15번째 게시글을 조회하는 SQL을 작성하시오. (LIMIT, OFFSET 사용)
select * from board order by board_id desc limit 5 offset 10;
7. board_like 테이블을 활용해서, 좋아요를 2번 이상 받은 게시글의 board_id만 조회하는 SQL을 작성하시오.
SELECT board_id, count(*) FROM BOARD_LIKE group by board_id having count(*) > 2
8. 위 결과(좋아요 2번 이상 받은 게시글)를 활용해서, 해당 게시글들의 제목과 조회수를 조회하는 SQL을 작성하시오. (서브쿼리 사용)
select title, view_count
from board
where board_id in (
SELECT board_id
FROM BOARD_LIKE
group by board_id
having count(*) > 2
);