📘꼬부기의 성장서재/이기적SQLD 기출문제

GROUP BY, HAVING절

서화 2026. 3. 30. 22:28

✔️ GROUP BY란

GROUP BY는 특정 컬럼을 기준으로 데이터를 그룹화하고, 합계, 평균, 개수 같은 집계 결과를 구할 때 사용하는 문법이다. 쉽게 말하면 여러 행을 어떤 기준으로 묶어서 하나의 요약 결과로 바꿔주는 역할이다

✔️ GROUP BY 실행 흐름

GROUP BY는 SQL 작성 순서만 보면 뒤에 나오지만, 실제 실행 순서에서는 FROM, WHERE 다음에 실행되고 SELECT보다 먼저 처리된다. 따라서 먼저 테이블을 정하고, 필요하면 WHERE로 조건을 걸러낸 다음 같은 값끼리 그룹을 만들어서  마지막에 SELECT로 보여줄 결과를 정한다

그래서 GROUP BY를 이해할 때는 “행을 먼저 묶고, 그다음 집계 결과를 보여준다”는 순서로 생각하는 게 편하다

✔️ GROUP BY 기본 예시

예시) 수강생 정보 테이블에서 소속반별 학생수 구하기

SELECT 소속반, COUNT(*) AS 반별인원수
FROM 수강생정보
GROUP BY 소속반;

소속반을 기준으로 같은 값끼리 먼저 묶고 각 그룹마다 COUNT(*) 개수를 센다 GROUP BY를 사용하면 여러 행을 하나의 그룹으로 요약해서 볼 수 있다

✔️ GROUP BY를 쓰면 행이 줄어드는 이유

GROUP BY를 사용하면 원본 테이블의 행 수 그대로 나오는 것이 아니라, 그룹 기준 컬럼의 종류 수만큼 결과가 줄어든다.

예시) 학생이 9명이 있을때 소속반 종류가 A, B, C 세 개뿐이면 결과는 3행만 나온다.

따라서 GROUP BY는 “원본 데이터 전체를 그대로 보여주는 문법”이 아니라 “같은 값을 묶어서 대표 결과만 보여주는 문법”이다

✔️ GROUP BY 사용 시 주의사항

GROUP BY를 쓰면 SELECT절에는 GROUP BY에 명시한 컬럼, 표현식, 또는 집계 함수만 사용할 수 있다.
그룹화가 끝난 뒤에는 이미 행이 줄어들었기 때문에 그룹 기준이 아닌 일반 컬럼은 어떤 값을 보여줘야 할지 결정할 수 없기 때문이다

오류 나는 SQL예시

SELECT 소속반, 학생이름, COUNT(*)
FROM 수강생정보
GROUP BY 소속반;

소속반 기준으로는 그룹이 묶였지만, 각 그룹 안에 학생이 여러 명이 있으므로 학생이름에 어떤 값을 표시해야 할지 정할 수 없어서 오류가 발생한다 그래서 GROUP BY를 사용할 때는 “내가 SELECT에 쓴 컬럼이 그룹 기준인지, 아니면 집계 결과인지”를 꼭 확인해야 한다

✔️ GROUP BY에는 표현식도 사용할 수 있다

✔️ GROUP BY와 함께 쓰는 집계 함수

GROUP BY는 보통 집계 함수와 같이 사용한다  집계 함수는 여러 행을 입력받아 하나의 결과를 반환하는 함수다 대표적으로 COUNT, SUM, AVG, MAX, MIN이 있다.

따라서 GROUP BY가 같은 값끼리 묶는 역할이라면 집계 함수는 묶인 데이터에 대해 개수, 합계, 평균, 최대값, 최소값 같은 요약값을 구하는 역할이다

COUNT 함수

COUNT는 그룹별 행의 개수를 세는 함수다  중요한 점은 COUNT()와 COUNT(컬럼)의 차이다

COUNT()는 NULL 여부와 상관없이 전체 행 수를 세고, COUNT(컬럼)은 해당 컬럼에서 NULL이 아닌 값만 센다.

따라서 COUNT는 같은 개수 세기 함수처럼 보여도 무엇을 기준으로 세느냐에 따라 결과가 달라질 수 있다.

예시)

SELECT 학생ID,
       COUNT(*) AS 전체건수,
       COUNT(성적) AS 유효성적건수
FROM 성적표
GROUP BY 학생ID;

학생의 성적이 전부 NULL일때 COUNT(*)는 3이지만, COUNT(성적)은 0으로 나온다. 즉 전체 행은 3개 존재하지만 실제 값이 있는 성적은 없다는 뜻이다

또한 COUNT(*), COUNT(1), COUNT(0)도 모두 같은 의미다 셋 다 결국 NULL을 포함해 행 수를 센다고 이해하면 된다

SUM과 AVG 함수

SUM은 그룹별 합계를 구하고, AVG는 그룹별 평균을 구하는 함수다

두 함수 모두 숫자형 데이터에만 사용할 수 있고, NULL 값은 무시하고 계산한다

다만 입력값이 전부 NULL이면 결과도 NULL이 된다 따라서 NULL이 하나 섞여 있다고 무조건 결과가 NULL이 되는 것은 아니고, 계산 가능한 값들끼리만 집계한 뒤 결과를 내는 방식이다

예시)

SELECT 학생ID,
       AVG(성적) AS 평균성적,
       SUM(성적) AS 성적합계
FROM 성적표
GROUP BY 학생ID;

모든 성적이 NULL이기 때문에 AVG와 SUM 결과도 NULL로 나온다. 반대로 값이 100, 70, NULL이라면 SUM은 NULL을 제외하고 170을 계산하고, AVG도 NULL을 제외한 두 개의 값만 가지고 평균을 구한다

MAX와 MIN 함수

MAX는 최대값, MIN은 최소값을 구하는 함수다. 이 함수들도 NULL은 무시하고 집계한다

또 숫자뿐 아니라 문자, 날짜 자료형에도 사용할 수 있다는 점이 특징이다. 예를 들어 숫자에서는 가장 큰 수와 작은 수를 찾고, 문자에서는 사전순 기준, 날짜에서는 가장 늦은 날짜와 가장 빠른 날짜를 찾는 식으로 사용할 수 있다

예시)

SELECT 학생ID,
       MAX(성적) AS 최고성적,
       MIN(성적) AS 최저성적
FROM 성적표
GROUP BY 학생ID;

이 경우도 NULL 값은 무시되며, 전부 NULL이면 결과는 NULL이 된다.

MAX, MIN도 NULL을 만나면 멈춘다가 아니라 NULL을 빼고 계산한다

✔️ GROUP BY 없이 집계 함수 사용 가능할까?

GROUP BY 없이 집계 함수를 사용하면 테이블 전체를 하나의 그룹으로 간주해서 집계한다.

예를 들어 전체 행 수를 세고 싶다면 그냥 COUNT(*)만 써도 된다. 이 경우는 “그룹을 안 나눈다”가 아니라 전체를 하나의 그룹으로 묶는다고 이해하면 편하다

SELECT COUNT(*)
FROM 성적표;

일반 컬럼과 집계 함수를 함께 사용하려면 반드시 GROUP BY가 필요하다

예를 들어 학생ID와 COUNT(*)를 같이 쓰고 싶다면 학생ID로 그룹화해야 한다 그렇지 않으면 전체를 하나의 그룹으로 본 상태에서 학생ID를 어떤 값으로 표시해야 할지 알 수 없어서 오류가 난다

✔️ 공집합과 집계 함수

조건에 맞는 행이 하나도 없는 공집합 상황도 시험에서 자주 나온다.

일반 컬럼 조회는 결과가 0행으로 끝나지만, 집계 함수는 보통 NULL을 반환한다. 단 COUNT는 예외적으로 0을 반환한다.

따라서 공집합을 만났을 때 “행이 아예 없는 결과”와 “집계 결과 한 줄이 나오는데 값이 NULL인 경우”를 구분해서 봐야 한다.

✔️ HAVING절이란?

HAVING은 GROUP BY로 그룹화한 결과에 조건을 거는 절이다
따라서 WHERE는 그룹화 전에 개별 행을 필터링하고, HAVING은 그룹화 후 집계 결과를 기준으로 다시 한 번 거르는 역할을 한다. 쉽게 말하면 WHERE는 원본 데이터에 대한 조건, HAVING은 집계 결과에 대한 조건이다

예시) 반별 인원수를 구한 뒤, 그중 인원수가 3명 이상인 반만 보고 싶다면 HAVING을 사용한다. 이때 COUNT(*) 같은 집계 함수 결과를 조건으로 걸 수 있다.

✔️ WHERE와 HAVING 차이

WHERE는 GROUP BY 전에 실행되기 때문에 개별 행 단위 조건에 사용한다

반면 HAVING은 GROUP BY 이후 실행되기 때문에 COUNT, SUM, AVG 같은 집계 결과를 조건으로 걸 때 사용한다

예시) 급여가 3000 이상인 직원만 먼저 뽑고 싶으면 WHERE를 쓰고, 부서별 평균 급여가 4000 이상인 부서만 보고 싶으면 HAVING을 써야 한다

✔️ 핵심 정리

GROUP BY는 데이터를 특정 기준으로 묶는 문법이고, HAVING은 그렇게 묶인 결과에 조건을 거는 문법이다

GROUP BY를 쓰면 SELECT에는 그룹 기준 컬럼이나 집계 함수만 올 수 있다는 점을 기억해야 한다.

COUNT는 NULL 포함 여부에 따라 결과가 달라질 수 있고, SUM, AVG, MAX, MIN은 NULL을 무시하지만 전부 NULL이면 결과도 NULL이 된다.

또 GROUP BY 없이 집계 함수를 쓰면 전체를 하나의 그룹으로 본다는 점, 공집합에서 COUNT는 0이고 다른 집계 함수는 NULL이 될 수 있다는 점도 같이 정리해두면 좋다.

'📘꼬부기의 성장서재 > 이기적SQLD 기출문제' 카테고리의 다른 글

JOIN  (0) 2026.04.01
ORDER BY절  (0) 2026.03.31
WHERE절  (0) 2026.03.29
함수(Function)  (0) 2026.03.28
본질식별자 VS 인조식별자  (0) 2026.03.24