최원종의 개발 블로그

GROUP BY 와 HAVING 절 - 19 본문

MySQL

GROUP BY 와 HAVING 절 - 19

chl6698 2026. 4. 6. 16:49

GROUP BY 개념과 기본 쿼리

GROUP BY는 같은 값을 가진 행들을 묶어서 그룹 단위로 집계할 때 사용

비유: 영수증 묶음
  편의점 영수증이 100장 있다고 가정합니다.
  날짜별로 묶으면 → 날짜별 총 구매 금액을 알 수 있습니다.
  상품별로 묶으면 → 상품별 판매 수량을 알 수 있습니다.
  GROUP BY 는 이 "묶는 기준"을 정하는 명령어입니다.

 


구조

SELECT 그룹컬럼, 집계함수
FROM 테이블명
GROUP BY 그룹컬럼;
use sns; 

-- GROUP BY 없이 : 전체 좋아요 개수 출력 
select count(*) as 전체좋아요수
from like_log;

select * from like_log;


-- 게시글 별 좋아요 수 
select post_id, count(*) as 좋아요수
from like_log
group by post_id;

 


GROUP BY 동작 원리

쿼리 실행 흐름:

  1. FROM like_log        → like_log 테이블 전체 데이터를 가져옴
  2. GROUP BY post_id     → post_id 값이 같은 행끼리 하나의 그룹으로 묶음
  3. COUNT(*) 집계        → 각 그룹 안의 행 수를 셈
  4. SELECT               → post_id 와 집계 결과를 화면에 출력

 


집계 함수 종류

함수 역할 예시
COUNT(*) 행 수 게시글별 좋아요 수
COUNT(컬럼) NULL 제외 행 수 점수가 있는 수강 기록 수
SUM(컬럼) 합계 상태별 총 주문 금액
AVG(컬럼) 평균 사용자별 평균 조회수
MAX(컬럼) 최댓값 카테고리별 최고 가격
MIN(컬럼) 최솟값 카테고리별 최저 가격
-- 그룹바이와 집계함수 모두 사용해보기 
select
	post_id, 
    count(*) as 좋아요수,
    min(created_at) as 첫번째좋아요,
    max(created_at) as 마지막좋아요
from like_log
group by post_id
order by 좋아요수 desc;

그룹바이 사용 시 작성하면 안 되는 쿼리 예시

-- 그룹바이 사용시 안되는 쿼리  1
select user_id, title,  count(*)
from post
group by user_id;

select *  from post;
-- title 컬럼을 넣는 순간 
-- (오늘 날씨가 정말 좋네요, 맛집 추천 받아요) 두개 데이중 무엇을 출력해야 될지 판단 불가 

-- 그룹바이 사용시 안되는 쿼리  2


select id, count(*)
from post
where count(*) >= 3
group by id;

-- 오류 발생 : WHERE 절에는 집계 함수를 사용할 수 없습니다. 
-- 이유 ? :  WHERE 절은 그룹이 만들어지지 전에 실행이 됩니다. 
--          즉, 아직 COUNT 결과가 존재하지 않는 시점이라 사용이 불가능 하다. 
-- 그럼 group by 는 where 못 사용하게 되나요. 맞습니다.
-- 대신 HAVING 절을 사용해야 합니다
더보기

1번 

 

2번

 


HAVING

  • 그룹바이 절에 필터는 WHERE 대신 HAVING을 사용해야 한다
  • HAVING 은 GROUP BY 로 만들어진 그룹에 조건을 적용하는 절이다
  • WHERE 가 개별 행을 필터링한다면, HAVING 은 완성된 그룹을 필터링한다
WHERE  : 행 단위 필터  → 그룹이 만들어지기 전
HAVING : 그룹 단위 필터 → 그룹이 만들어진 후

핵심 차이:
  WHERE  에서는 집계함수(COUNT, SUM, AVG...) 사용 불가
  HAVING 에서는 집계함수 사용 가능

HAVING 구조

SELECT 그룹컬럼, 집계함수
FROM 테이블명
GROUP BY 그룹컬럼
HAVING 집계함수 조건;

사용 코드

-- 예제 1 
-- 좋아요가 2개 이상인 게시글만 조회하고 싶다면 어떻게 쿼리를 작성해야 될까? 
-- 좋아요 개수 --> like_log 7개의 좋아요 저장되어 있음 
select 
	post_id, count(*) as 좋아요수
from like_log
group by post_id
having count(*) >= 2;


-- 예제 2 
-- WHERE 와 HAVING는 역할이 달라서 한 쿼리에 함께 쓸 수 있습니다. 
-- 조회수 120이상 게시글을 중 좋아요 2개 이상인 게시글만 출력하시오.
-- 게시글 타이틀, 좋아요 수가 나와요 함.  
select * from post;
select * FROM like_log; 

select
	p.title,
    count(l.id) as 좋아요수
from post p 
join like_log l on p.id = l.post_id
where p.view_count >= 120
group by p.id, p.title
having count(l.id) >= 2
order by 좋아요수 desc; 

-- WHERE 절 조회수 120 이상인 게시글만 먼저 추림 
-- 남은 게시글로 GROUP BY 실행 
-- HAVING 으로 좋아요 2개 이상 그룹만 출력
더보기

예제1

예제 2


SQL의 논리적 실행 순서

1. FROM / JOIN  : 테이블에서 데이터를 가져온다
2. WHERE        : 개별 행을 필터링한다          (집계 전)
3. GROUP BY     : 남은 행들을 같은 값끼리 바구니에 담는다
4. HAVING       : 완성된 바구니 중 조건에 맞는 바구니만 남긴다  (집계 후)
5. SELECT       : 화면에 보여줄 컬럼을 추출한다
6. ORDER BY     : 마지막으로 정렬한다
7. LIMIT        : 행 수를 제한한다

실습 코드

-- 실습 1 
-- 게시글 별 좋아요 수를 출력하시오 단, 좋아요가 없는 게시글도 출력이 되어야 한다. 
-- 게시글 타이틀, 좋아요 수 
-- [결과확인] 게시글 4번 타이틀도 출력이 되어야 함. 
select
	p.id, p.title, count(l.id) as 좋아요수
from post p
left join like_log l on p.id = l.post_id
group by p.title, p.id;


-- 실습 2
-- 사용자별 작성 게시글 수 , 게시글 하나도 작성안한 회원도 나와야 한다. 
-- 닉네임, 작성글 수 



-- 실습 3 
-- 사용자별 게시글에 평균게시글조회수 (단 2개 이상인 사람만) 
-- 닉네임, 게시글 수, 평균조회수
더보기

실습 1

실습 2

실습 3

문제 만들어보기

만든 문제: sns DB에서 사용자의 이름, 작성한 게시물제목, 게시물에 달린 댓글수, 게시물평균조회수(내림차순), 사용자 email (@ 앞까지만 보이게, substring사용)를 출력하시오

답안:

select
	u.nickname as 사용자이름,
    p.title as 게시물제목,
	count(DISTINCT c.id) as 포스트별댓글수,
    p.view_count as 조회수,
    substring(email, 1, locate('@',email) -1) as 사용자email
from user u
inner join post p on u.id = p.user_id
inner join comment c on p.id = c.post_id
group by p.id
order by 조회수 desc;

 

'MySQL' 카테고리의 다른 글

SQL 쿼리 실행 순서  (0) 2026.04.06
DISTINCT 와 COUNT - 20  (0) 2026.04.06
MySQL 주요 함수 - 18  (0) 2026.04.05
샘플 데이터 활용 문제 - 17 _ 1(인라인 필터 추가 설명)  (1) 2026.04.05
샘플 데이터 활용 문제 - 17  (1) 2026.04.04