← 개념서태블릿/PC 버전
2과목 · SQL 기본 및 활용·8

집계 함수

COUNT/SUM/AVG/MIN/MAX의 NULL 처리, DISTINCT 사용, GROUP BY와의 관계를 정리합니다.

1. 집계 함수란

여러 행을 받아 하나의 결과를 돌려주는 함수. 단독으로 쓰면 전체 테이블을 1행으로 요약하고, GROUP BY와 함께 쓰면 그룹별로 1행씩 돌려줍니다.

2. 대표 함수

함수 설명
COUNT(*) 모든 행 수 (NULL 포함)
COUNT(col) col이 NOT NULL인 행 수
COUNT(DISTINCT col) 중복 제거한 값의 수
SUM(col) 합계 (NULL 무시)
AVG(col) 평균 (NULL 무시)
MIN(col) / MAX(col) 최솟값 / 최댓값 (NULL 무시)

NULL 처리의 차이

  • COUNT(*) 는 NULL도 센다.
  • COUNT(col) 은 col이 NULL인 행을 세지 않는다.
  • SUM/AVG/MIN/MAX 는 NULL을 무시하고 계산.
-- 10명 중 bonus가 3명에게만 값이 있을 때
SELECT COUNT(*),      -- 10
       COUNT(bonus),  -- 3
       AVG(bonus),    -- 3명 평균 (10명 나눔 아님)
       SUM(bonus)     -- 3명 합
FROM emp;

3. GROUP BY와의 관계

SELECT에 등장하는 컬럼은 반드시 다음 중 하나:

  1. GROUP BY에 나열된 컬럼
  2. 집계 함수의 인자
-- ❌ 오류: name이 GROUP BY에도 없고 집계도 아님
SELECT dept_id, name, AVG(salary) FROM emp GROUP BY dept_id;

-- ✅
SELECT dept_id, AVG(salary) FROM emp GROUP BY dept_id;

4. DISTINCT와 함께

SELECT COUNT(DISTINCT dept_id) FROM emp;  -- 고유 부서 수
SELECT AVG(DISTINCT salary)    FROM emp;  -- 중복 급여를 한 번씩 평균

5. 조건부 집계 (FILTER / CASE)

ANSI의 FILTER는 PostgreSQL 등이 지원, Oracle/MySQL은 CASE 패턴을 씁니다.

-- PostgreSQL
SELECT
  COUNT(*) FILTER (WHERE salary >= 5000000) AS high_paid,
  COUNT(*) FILTER (WHERE salary <  5000000) AS low_paid
FROM emp;

-- 범용: CASE + SUM/COUNT
SELECT
  SUM(CASE WHEN salary >= 5000000 THEN 1 ELSE 0 END) AS high_paid,
  SUM(CASE WHEN salary <  5000000 THEN 1 ELSE 0 END) AS low_paid
FROM emp;

6. HAVING — 집계 결과 필터

WHERE에는 집계 함수를 쓸 수 없으니, 집계 후 필터는 HAVING으로.

SELECT dept_id, COUNT(*) AS cnt
FROM emp
GROUP BY dept_id
HAVING COUNT(*) >= 5;

7. 집계와 인덱스

  • MIN(col) / MAX(col) 은 col에 인덱스가 있으면 테이블 풀스캔 없이 빠르게 답.
  • COUNT(*) 전체 수는 테이블 크기가 크면 캐시된 통계를 쓰는 DBMS가 있음.

8. 자주 출제되는 포인트

  • COUNT(*) vs COUNT(col)NULL 처리 차이.
  • SELECT에 들어가는 컬럼은 GROUP BY 포함 또는 집계 중 하나.
  • WHERE엔 집계 불가, HAVING엔 가능.
  • AVG는 NULL을 무시하므로 분모가 전체 행수가 아님.
  • DISTINCT를 결합해 고유값 기반 집계 가능.

9. 요약 체크리스트

  • 다섯 가지 집계 함수의 NULL 처리 차이를 설명할 수 있다.
  • GROUP BY와 SELECT의 규칙을 답할 수 있다.
  • 조건부 집계를 CASE로 쓸 수 있다.
  • WHERE vs HAVING의 사용 시점을 안다.