[SQLD] COUNT와 NULL의 처리 기준 — 행 수·값의 개수·평균 비교

차곡코딩·2026년 9월 21일

SQL · SQLD 개념

목록 보기
1/1

COUNT(*)와 COUNT(컬럼)은 집계 대상이 다르다. 이 차이는 NULL이 포함된 데이터에서 분명하게 드러난다. 행 수, 값의 개수, 중복 제거, 평균의 분모를 구분해 정리한다.

데이터는 별도로 구성한 학습 예제다. 결과는 SQLite 기준이며, 교재나 특정 시험 회차의 문제를 옮긴 글은 아니다.

1. 예제 데이터와 집계 결과

CREATE TABLE scores (score INTEGER);
INSERT INTO scores VALUES (80), (NULL), (0), (80);

SELECT
    COUNT(*) AS row_count,
    COUNT(score) AS value_count,
    COUNT(DISTINCT score) AS distinct_count,
    SUM(score) AS total_score,
    AVG(score) AS average_score
FROM scores;
집계식결과집계 기준
COUNT(*)4전체 행 수
COUNT(score)3score가 NULL이 아닌 행 수
COUNT(DISTINCT score)2NULL과 중복을 제외한 값의 개수
SUM(score)160NULL을 제외한 값의 합
AVG(score)약 53.3333NULL을 제외한 값의 평균

COUNT(*)는 score가 NULL인 행도 포함한다. 반면 COUNT(score)는 해당 값이 NULL인 행을 제외한다. COUNT(DISTINCT score)의 집계 대상은 서로 다른 값인 80과 0이다.

2. NULL과 0의 구분

0은 실제 숫자 값이므로 COUNT(score)에 포함된다. 이 예제에서 NULL은 점수가 기록되지 않은 상태로 해석할 수 있다. 점수가 0이라는 사실과 점수를 알 수 없다는 상태는 서로 다르다.

집계 결과를 해석할 때는 NULL을 단순히 0처럼 취급하지 않아야 한다. 두 값을 동일하게 처리하면 데이터가 가진 의미도 달라진다.

3. AVG의 분모

AVG(score)는 NULL이 아닌 세 값의 평균을 계산한다.

(80 + 0 + 80) / 3 = 53.3333...

전체 행 수인 4로 나누면 40이 된다. 이는 미기록 점수를 0으로 간주한 경우와 같은 계산이며, 원래의 평균과는 기준이 다르다. NULL을 0으로 대체할지는 함수 사용의 편의가 아니라 데이터의 의미와 업무 규칙으로 결정해야 한다.

4. 모든 값이 NULL인 경우

NULL인 두 행만 있다고 가정하면 SQLite의 결과는 다음과 같다.

집계식결과
COUNT(*)2
COUNT(score)0
SUM(score)NULL
AVG(score)NULL

합계와 평균을 계산할 유효한 값이 없다는 상태는 계산 결과가 0이라는 의미와 다르다. 특히 SUM의 결과를 항상 숫자라고 가정하지 않도록 주의해야 한다.

5. 집계식 확인 순서

먼저 집계 대상이 행인지 값인지 확인한다. 다음으로 NULL 제외 여부와 중복 제거 여부를 구분한다. 평균은 분자뿐 아니라 분모에 포함되는 값의 개수까지 확인한다. 이 기준을 적용하면 집계 함수별 결과를 일관되게 설명할 수 있다.

참고 문서

profile
비전공자의 개발 성장 기록. 바이브코딩 프리랜서 경험부터 Python·SQL·AI 서비스 개발까지

0개의 댓글