이 문서는 시험에서 틀렸던 SQL 쿼리들을 복습하면서,
출력 항목 → 테이블 출처 → JOIN → 조건 → 정렬 기준 순서로 풀이 흐름을 정리했다.
다시 봤을 때 왜 그렇게 쿼리를 짰는지 흐름이 기억나도록 쿼리 위에 간단히 흐름을 덧붙였다.
오늘 시험에서 게시판 관련 SQL 문제를 풀었는데, 생각보다 시간이 부족해서 아쉬움이 좀 남았다. 전체적인 구조는 익숙했지만, JOIN 조건이 누락되거나 LEFT JOIN을 사용하지 않아서 결과가 달라진 경우가 있었고, 시험이 끝난 직후 곧바로 복습을 진행했다. 틀렸던 부분은 수정해서 다시 정리해봤다.
| 테이블 | 간단한 설명 |
|---|---|
member | 회원 정보 저장 |
board | 게시판 목록 관리 |
article | 게시물 정보 저장 |
articleReply | 댓글 정보 저장 |
like | 좋아요 기록 저장 |
member: 로그인 ID, 닉네임, 실명 같은 회원 정보를 저장한다. 게시글, 댓글, 좋아요에 전부 연결되는 핵심 테이블.board: 게시판 이름을 저장하는 테이블. 자유게시판, 공지사항 등.article: 실제 게시물 데이터를 담는다. 제목, 내용, 조회수, 작성자 등이 포함됨.articleReply: 댓글을 저장. 어떤 게시물에 누가 댓글을 달았는지를 저장.like: 어떤 회원이 어떤 게시물을 좋아요 했는지 저장. 복합키로 중복 방지.member: 게시판에서 활동하는 사람 그 자체. 글을 쓰고 댓글을 달고 좋아요도 누르는 모든 주체가 이 테이블에 담겨 있다. 게시판 시스템에서 회원 정보를 나타내는 핵심 테이블로, 사용자 프로필 역할을 한다고 볼 수 있다.board: 책장이 여러 개 있는 도서관의 책꽂이article: 책꽂이에 꽂힌 책 한 권 한 권articleReply: 책에 붙은 포스트잇 메모like: 책에 찍힌 추천 도장❶ 출력: 게시물 수
❷ 출처: article
❸ JOIN: 없음
❹ 조건: 없음
❺ 정렬: 없음
SELECT COUNT(*) -- 전체 행 개수(= 게시물 수)를 센다
FROM article; -- 게시물 테이블에서
실행 결과 예시
| 게시물 수 |
|---|
| 10 |
❶ 출력: 전체 조회수 합계
❷ 출처: article
❸ JOIN: 없음
❹ 조건: 없음
❺ 정렬: 없음
SELECT SUM(hit) -- hit 컬럼의 값을 모두 더함 (조회수 총합)
FROM article; -- 게시물 테이블에서
실행 결과 예시
| 조회수 총합 |
|---|
| 659 |
❶ 출력: 게시물 번호, 제목, 본문, 조회수, 닉네임, 작성일
❷ 출처: article, member, board
❸ JOIN: article → member, article → board
❹ 조건: 제목에 '제' 포함, 자유게시판
❺ 정렬: 작성일 내림차순
SELECT art.ano, -- 게시물 번호
art.title, -- 제목
art.`body`, -- 본문 내용
art.hit, -- 조회수
mem.nname, -- 작성자 닉네임
art.regDate -- 작성일
FROM article AS art -- 게시물 테이블
INNER JOIN `member` AS mem ON art.mno = mem.mno -- 작성자 정보 연결
INNER JOIN board AS bo ON art.bno = bo.bno -- 게시판 정보 연결
WHERE art.title LIKE '%제%' -- 제목에 '제' 포함 필터
AND bo.bname = '자유게시판' -- 자유게시판만
ORDER BY art.regDate DESC; -- 작성일 기준 최신순 정렬
실행 결과 예시
| 게시물 번호 | 제목 | 내용 | 조회수 | 닉네임 | 작성일시 |
|---|---|---|---|---|---|
| 1 | 제목1 | 내용1 | 10 | 신출귀몰 | 2020-03-03 12:30:00 |
| 2 | 제목2 | 내용2 | 23 | 신출귀몰 | 2021-05-06 15:12:00 |
❶ 출력: 게시판 이름, 게시물 수
❷ 출처: board, article
❸ JOIN: board → article (LEFT JOIN)
❹ 조건: 없음
❺ 정렬: 게시물 수 내림차순
SELECT bo.bname, -- 게시판 이름
COUNT(art.ano) AS 게시물수 -- 게시물 개수
FROM board AS bo -- 게시판 테이블 기준
LEFT JOIN article AS art ON bo.bno = art.bno -- 게시물 연결 (없어도 포함)
GROUP BY bo.bname -- 게시판 단위로 묶기
ORDER BY 게시물수 DESC; -- 게시물 많은 순으로 정렬
실행 결과 예시
| 게시판 이름 | 게시물 수 |
|---|---|
| 자유게시판 | 5 |
| 공지사항 | 2 |
| 질문과답변 | 3 |
❶ 출력: 제목, 본문, 닉네임, 작성일
❷ 출처: article, member
❸ JOIN: article → member
❹ 조건: 날짜 BETWEEN 2023-10-01 AND 2024-04-01
❺ 정렬: 작성일 내림차순
SELECT art.title, -- 제목
art.`body`, -- 본문
mem.nname, -- 닉네임
art.regDate -- 작성일
FROM article AS art -- 게시물 테이블
INNER JOIN `member` AS mem ON art.mno = mem.mno -- 작성자 정보 연결
WHERE art.regDate BETWEEN '2023-10-01' AND '2024-04-01' -- 날짜 조건
ORDER BY art.regDate DESC; -- 최신순 정렬
실행 결과 예시
| 제목 | 내용 | 닉네임 | 작성일시 |
|---|---|---|---|
| 제목9 | 내용9 | 힘쎈장사 | 2024-03-03 23:12:00 |
❶ 출력: 게시판 이름, 댓글 수
❷ 출처: board, article, articleReply
❸ JOIN: board → article → articleReply
❹ 조건: 없음
❺ 정렬: 댓글 수 내림차순, LIMIT 1
SELECT bo.bname, -- 게시판 이름
COUNT(*) AS 댓글수 -- 댓글 개수
FROM `board` AS bo -- 게시판 테이블
INNER JOIN article AS art ON bo.bno = art.bno -- 게시물 연결
INNER JOIN `articleReply` AS re ON art.ano = re.ano -- 댓글 연결
GROUP BY bo.bname -- 게시판 단위로 묶기
ORDER BY 댓글수 DESC -- 댓글 많은 순 정렬
LIMIT 1; -- 상위 1개만
실행 결과 예시
| 게시판 이름 | 댓글 수 |
|---|---|
| 자유게시판 | 7 |
❶ 출력: 게시물 번호, 제목, 댓글 수
❷ 출처: article, articleReply
❸ JOIN: article → articleReply
❹ 조건: 없음
❺ 정렬: 댓글 수 내림차순, 같으면 게시물 번호 오름차순
SELECT art.ano, -- 게시물 번호
art.title, -- 게시물 제목
COUNT(*) AS 댓글수 -- 댓글 개수
FROM article AS art -- 게시물 테이블
INNER JOIN `articleReply` AS re ON art.ano = re.ano -- 댓글 연결
GROUP BY art.ano -- 게시물 단위로 묶기
ORDER BY 댓글수 DESC, art.ano ASC; -- 댓글 많은 순, 같으면 번호 오름차순
실행 결과 예시
| 게시물 번호 | 제목 | 댓글 수 |
|---|---|---|
| 9 | 제목9 | 5 |
| 8 | 제목8 | 2 |
| 6 | 제목6 | 3 |
❶ 출력: 회원번호, 닉네임, 조회수 총합
❷ 출처: member, article
❸ JOIN: member → article
❹ 조건: 없음
❺ 정렬: 조회수 총합 내림차순, 같으면 회원번호 오름차순
SELECT mem.mno, -- 회원 번호
mem.nname, -- 닉네임
SUM(hit) AS 조회수총합 -- 게시물 조회수 합계
FROM `member` AS mem -- 회원 테이블
INNER JOIN article AS art ON mem.mno = art.mno -- 회원이 쓴 게시물 연결
GROUP BY mem.mno -- 회원 단위로 묶기
ORDER BY 조회수총합 DESC, mem.mno ASC; -- 조회수 높은 순, 같으면 번호 오름차순
실행 결과 예시
| 회원 번호 | 닉네임 | 조회수 총합 |
|---|---|---|
| 1 | 신출귀몰 | 300 |
❶ 출력: 제목, 본문, 닉네임, 조회수
❷ 출처: article, member
❸ JOIN: article → member
❹ 조건: 없음
❺ 정렬: 조회수 내림차순, LIMIT 3
SELECT art.title, -- 제목
art.`body`, -- 본문
mem.nname, -- 닉네임
art.hit -- 조회수
FROM article AS art -- 게시물 테이블
INNER JOIN `member` AS mem ON art.mno = mem.mno -- 작성자 정보 연결
ORDER BY art.hit DESC -- 조회수 높은 순 정렬
LIMIT 3; -- 상위 3개만
실행 결과 예시
| 제목 | 내용 | 닉네임 | 조회수 |
|---|---|---|---|
| 제목4 | 내용4 | 구국의 영웅 | 100 |
| 제목7 | 내용7 | 구국의 영웅 | 87 |
| 제목1 | 내용1 | 신출귀몰 | 70 |
❶ 출력: 로그인 ID, 실명, 좋아요 수
❷ 출처: member, like
❸ JOIN: member → like
❹ 조건: 없음
❺ 정렬: 좋아요 수 내림차순, LIMIT 1
SELECT mem.loginId, -- 로그인 ID
mem.rname, -- 실명
COUNT(*) AS 좋아요개수 -- 좋아요 개수
FROM `member` AS mem -- 회원 테이블
INNER JOIN `like` AS li ON mem.mno = li.mno -- 좋아요 기록 연결
GROUP BY mem.loginId, mem.rname -- 회원 단위로 묶기
ORDER BY 좋아요개수 DESC -- 좋아요 많은 순 정렬
LIMIT 1; -- 1명만 출력
실행 결과 예시
| 로그인 ID | 실명 | 좋아요 개수 |
|---|---|---|
| user4 | 유관순 | 5 |
like는 SQL 예약어라 테이블명으로 쓸 땐 백틱(``)이 필요하다.LEFT JOIN을 써야 한다.BETWEEN으로 명확히 구간 지정.LIMIT만 쓰면 어떤 기준으로 잘렸는지 모를 수 있으니 ORDER BY와 함께 사용해야 정확한 결과를 얻을 수 있다.| 항목 | 주의할 점 | 해결 방법 |
|---|---|---|
| like 테이블 | 예약어 충돌 | 백틱(`) 또는 이름 변경 |
| 게시판별 게시물 수 | 게시물 없는 경우 누락 | LEFT JOIN 사용 |
| 날짜 비교 | 범위 애매할 수 있음 | BETWEEN '시작' AND '끝' 사용 |
| LIMIT 사용 | 정렬 기준 없으면 불확실 | ORDER BY와 같이 사용 |
| 좋아요 많은 회원 | GROUP BY 후 정렬 빠짐 | ORDER BY COUNT(*) DESC 추가 |
전체적으로 어렵진 않았는데, 쿼리 조건 하나 빠지면 결과가 완전히 달라져서 꼼꼼하게 읽는 연습이 필요하다고 느꼈다. 실수한 부분은 대부분 JOIN 조건이나 WHERE 조건이 부족해서 나온 결과였고, LEFT JOIN을 써야 하는 상황도 실습하면서 다시 떠올렸다. 특히 좋아요 많은 회원 찾는 문제에서 ORDER BY 없이 LIMIT만 쓴 실수는 꼭 기억해둬야겠다. 다음엔 처음부터 문제 조건을 더 명확히 분석하고, 쿼리를 짜기 전에 어떤 테이블이 어떤 관계인지 생각하고 시작해야겠다.