[SECTION09. 집계함수와 GROUP BY / HAVING]
| 함수 | 의미 |
|---|---|
| COUNT(컬럼 또는 *) | 행의 개수 |
| SUM(컬럼) | 합계 |
| AVG(컬럼) | 평균 |
| MAX(컬럼) | 최댓값 |
| MIN(컬럼) | 최솟값 |
-- 전체 게시글 수
SELECT COUNT(*) FROM board;
-- content가 NULL이 아닌 게시글 수 (컬럼명을 넣으면 NULL은 제외하고 셈)
SELECT COUNT(content) FROM board;
-- 전체 게시글의 조회수 합계
SELECT SUM(view_count) FROM board;
-- 전체 게시글의 평균 조회수
SELECT AVG(view_count) FROM board;
-- 조회수가 가장 높은 값
SELECT MAX(view_count) FROM board;
-- 조회수가 가장 낮은 값
SELECT MIN(view_count) FROM board;
select
count(*) as 전체게시글수,
max(view_count) as 조회수최댓값,
min(view_count) as 조회수최솟값,
avg(view_count) as 조회수평균,
sum(view_count) as 조회수총합
from board
AS로 결과 컬럼에 별명(alias)을 붙이면 결과를 읽기 쉬워집니다.
집계함수를 전체 테이블이 아니라 그룹별로 적용하고 싶을 때 사용합니다.
-- 카테고리별 게시글 수
SELECT category_id, COUNT(*) AS board_count
FROM board
GROUP BY category_id;
결과 예시:
| category_id | board_count |
|---|---|
| 1 | 6 |
| 2 | 3 |
| 3 | 4 |
| 4 | 7 |
category_id가 같은 행끼리 묶어서, 그 안에서 COUNT를 계산합니다.
-- 회원별 작성한 게시글 수
SELECT member_id, COUNT(*) AS board_count
FROM board
GROUP BY member_id;
-- 카테고리별 평균 조회수
SELECT category_id, AVG(view_count) AS avg_view
FROM board
GROUP BY category_id;
SELECT에 나열하는 컬럼은 GROUP BY에 포함된 컬럼 또는 집계함수로 감싼 컬럼이어야 합니다.
-- ❌ 잘못된 예: title은 그룹화 기준도 아니고 집계함수도 아님
SELECT category_id, title, COUNT(*) FROM board GROUP BY category_id;
-- ✅ 올바른 예
SELECT category_id, COUNT(*) FROM board GROUP BY category_id;
WHERE는 그룹화하기 전 행 단위로 조건을 거는 것이고, HAVING은 그룹화한 이후 그룹 단위로 조건을 거는 것입니다.
-- 게시글이 5개 이상인 카테고리만 조회
SELECT category_id, COUNT(*) AS board_count
FROM board
GROUP BY category_id
HAVING COUNT(*) >= 5;
select category_id, count(*) as board_count
from board
group by category_id
having board_count >= 5
-- 평균 조회수가 0보다 큰 카테고리만 조회
SELECT category_id, AVG(view_count) AS avg_view
FROM board
GROUP BY category_id
HAVING AVG(view_count) > 0;
-- member_id가 1~5인 게시글만 대상으로, 카테고리별 게시글 수를 구하고,
-- 그중 게시글 수가 2개 이상인 카테고리만 조회
SELECT category_id, COUNT(*) AS board_count
FROM board
WHERE member_id BETWEEN 1 AND 5
GROUP BY category_id
HAVING COUNT(*) >= 2;
실행 순서: WHERE(행 필터링) → GROUP BY(그룹화) → HAVING(그룹 필터링) → ORDER BY(정렬)
WHERE는 집계함수를 사용할 수 없습니다 (
WHERE COUNT(*) >= 2는 에러). 집계 결과에 조건을 걸려면 반드시 HAVING을 사용해야 합니다.
SELECT member_id, COUNT(*) AS board_count
FROM board
GROUP BY member_id
ORDER BY board_count DESC
LIMIT 3;
SELECT board_id, COUNT(*) AS comment_count
FROM comment
GROUP BY board_id
ORDER BY comment_count DESC
LIMIT 1;
SELECT board_id, COUNT(*) AS like_count
FROM board_like
GROUP BY board_id
ORDER BY like_count DESC;
1. board 테이블에서 전체 게시글 수와 평균 조회수를 함께 조회하는 SQL을 작성하시오.
select
count(*) as 전체게시글수,
avg(view_count) as 평균조회수
from board
2. comment 테이블에서 게시글(board_id)별 댓글 수를 조회하는 SQL을 작성하시오.
select
board_id,
count(*) as 댓글수
from comments
group by board_id
3. board 테이블에서 회원(member_id)별 게시글 수가 많은 순으로 정렬해서 조회하는 SQL을 작성하시오.
select
member_id,
count(*) as 작성게시글수
from board
group by board_id
order by 작성게시글수 desc
4. board 테이블에서 카테고리(category_id)별 게시글 수를 구하고, 그중 게시글 수가 3개 이상인 카테고리만 조회하는 SQL을 작성하시오.
select category_id, count(*) as 게시글수
from board
group by category_id
having 게시글수 >= 3;
5. board_like 테이블에서 게시글별 좋아요 수를 구하고, 좋아요 수가 가장 많은 게시글 1개만 조회하는 SQL을 작성하시오.
select board_id, count(*) as 좋아요수
from
board_like
group by board_id
order by 좋아요수 desc
limit 1
6. board 테이블에서 category_id가 1 또는 4인 게시글만 대상으로, 회원별 게시글 수를 구하고, 그중 2개 이상 쓴 회원만 조회하는 SQL을 작성하시오. (WHERE와 HAVING을 모두 사용)
select member_id, count(*) as 회원별게시글수
from board
where category_id in (1, 4)
group by member_id
having 회원별게시글수 >= 2
7. comment 테이블에서 회원(member_id)별로 작성한 댓글 수를 구하고, 댓글을 2개 이상 작성한 회원을 구하시오.
select member_id, count(*) 댓글수
from
comments
group by member_id
having 댓글수 >= 2