su-tudy 님의 블로그

GROUP BY와 HAVING 본문

DBMS/Part 2. DML

GROUP BY와 HAVING

su-tudy 2024. 9. 24. 22:13

 

𖤐 그룹화와 그룹 조건

 

집계함수만 쓰면 테이블 전체를 하나로 요약한 결과만 나온다. GROUP BY를 쓰면 특정 컬럼 기준으로 데이터를 묶어서 그룹별로 집계할 수 있다. HAVING은 그 그룹에 조건을 거는 역할이다.

 


𖤐 정리 노트 

 

✧ GROUP BY 없이 집계 vs GROUP BY 집계

차이를 먼저 이해하는 게 중요하다. 아래처럼 GROUP BY는 "그룹별로 쪼개서 집계" 할 때 사용한다.

-- GROUP BY 없이: 전체 직원의 평균 급여 하나만 반환
SELECT AVG(salary)
FROM employees;
-- 결과: 350

-- GROUP BY 사용: 부서별 평균 급여를 각각 반환
SELECT dept, AVG(salary)
FROM employees
GROUP BY dept;
-- 결과:
-- 개발팀  420
-- 디자인팀 310
-- 마케팅팀 290

 


✧ GROUP BY

동일한 값을 가진 행들을 하나의 그룹으로 묶어준다. 집계함수와 함께 쓰는 게 일반적이다.

SELECT column_name, 집계함수(column)
FROM table_name
WHERE condition         -- 그룹화 전 조건 (선택)
GROUP BY column_name
ORDER BY column_name;
-- 부서별 인원 수
SELECT dept, COUNT(*) AS 인원수
FROM employees
GROUP BY dept;

-- 부서별 급여 합계, 내림차순 정렬
SELECT dept, SUM(salary) AS 급여합계
FROM employees
GROUP BY dept
ORDER BY 급여합계 DESC;

 

여러 컬럼으로 그룹화

-- 부서 + 직급 조합별로 그룹화
SELECT dept, position, COUNT(*) AS 인원수
FROM employees
GROUP BY dept, position;

 


✧ 그룹화 전후 데이터 비교

GROUP BY를 적용하면 데이터가 어떻게 바뀌는지 흐름을 이해해 두면 좋다.

[원본 테이블 - employees]
name     dept      salary
김철수   개발팀     400
이영희   개발팀     500
박민준   디자인팀   300
최지원   디자인팀   350
홍길동   마케팅팀   280

              ↓ GROUP BY dept

[그룹화 후]
dept      COUNT(*)   AVG(salary)
개발팀     2          450
디자인팀   2          325
마케팅팀   1          280

GROUP BY를 하면 각 그룹이 하나의 행으로 합쳐진다. 그래서 GROUP BY 이후엔 그룹 기준 컬럼과 집계함수만 SELECT에 쓸 수 있다.

 


✧ HAVING - 그룹 조건

WHERE은 그룹화 전에 실행되기 때문에 집계 결과에 조건을 걸 수 없다. 그룹화 후 조건을 걸려면 HAVING을 써야 한다.

SELECT column_name, 집계함수(column)
FROM table_name
WHERE condition          -- 1. 그룹화 전 조건
GROUP BY column_name
HAVING 집계함수 조건      -- 2. 그룹화 후 조건
ORDER BY column_name;
-- 평균 급여가 350 이상인 부서만 조회
SELECT dept, AVG(salary) AS 평균급여
FROM employees
GROUP BY dept
HAVING AVG(salary) >= 350;

 

▸ WHERE vs HAVING 실행 시점

FROM
WHERE
GROUP BY
HAVING
SELECT
ORDER BY
LIMIT
WHERE / HAVING 실행 시점 집계함수 사용
WHERE 그룹화 전 ❌ 불가
HAVING 그룹화 후 ✅ 가능
-- WHERE과 HAVING 같이 쓰는 예시
-- 개발팀/디자인팀 중에서 평균 급여 350 이상인 부서만 조회
SELECT dept, AVG(salary) AS 평균급여
FROM employees
WHERE dept IN ('개발팀', '디자인팀')  -- 먼저 두 부서만 필터링
GROUP BY dept
HAVING AVG(salary) >= 350;            -- 그룹화 후 조건 적용

 


𖤐 체크포인트

 

🚨 오류 — GROUP BY를 사용할 때
GROUP BY를 사용할 때는 집계하지 않은 컬럼을 SELECT에 함께 쓰면 오류가 발생할 수 있다.

SELECT name, dept, COUNT(*) FROM employees GROUP BY dept; → name은 GROUP BY에 없고 집계함수도 아님
SELECT dept, COUNT(*) FROM employees GROUP BY dept; → 올바른 방법

🚨 주의 — 집계함수는 WHERE절에서 사용 불가
집계 함수 조건은 WHERE가 아니라 HAVING에서 처리해야 한다.

SELECT dept, AVG(salary) FROM employees WHERE AVG(salary) >= 350 GROUP BY dept; → 에러: WHERE에 집계함수 못 씀
SELECT dept, AVG(salary) FROM employees GROUP BY dept HAVING AVG(salary) >= 350; → 올바른 방법

 


𖤐 오늘의 한 줄 요약

 

GROUP BY는 특정 컬럼 기준으로 묶어서 그룹별 집계를 내는 것. HAVING그룹화 후에 조건을 거는 것. WHERE은 그룹화 전, HAVING은 그룹화 후 실행된다는 차이를 기억하자.

'DBMS > Part 2. DML' 카테고리의 다른 글

JOIN (INNER, LEFT, RIGHT, OUTER)  (0) 2024.10.11
COUNT, SUM, AVG, MAX, MIN  (0) 2024.09.23
ORDER BY와 LIMIT  (0) 2024.09.22
WHERE와 연산자  (0) 2024.09.20
SELECT, INSERT, UPDATE, DELETE  (0) 2024.09.17