정보처리기사 · SQL 6분 읽기

SQL NULL 연산·집계 함수·JOIN 차이: COUNT(*)와 OUTER JOIN 결과 예측

컬럼에 NULL이 들어 있을 때 COUNT(*), COUNT(컬럼), AVG(컬럼)의 결과는 어떻게 달라질까요? 4행짜리 작은 테이블로 WHERE·HAVING과 INNER·OUTER JOIN 결과 건수를 비교합니다.

이 글에서 익힐 것NULL이 포함된 테이블의 집계 결과와 INNER·LEFT·FULL OUTER JOIN의 결과 행 수를 정확히 계산하기규칙 설명 → SQL 용어·함수·절

SQL NULL·집계·JOIN 카드 10장

핵심 짚어보기

NULL의 두 가지 기본 규칙: 산술 연산은 NULL, 비교 연산은 UNKNOWN

SQL에서 NULL은 숫자 0이나 공백('')이 아니라 '아직 정의되지 않았거나 알 수 없는 값'입니다. 따라서 단일 행 안에서 NULL에 숫자를 더하거나 곱하면(예: NULL + 100, NULL * 0) 결과는 언제나 NULL입니다.

또한 WHERE 절에서 = NULL 이나 != NULL 로 비교하면 참(TRUE)도 거짓(FALSE)도 아닌 UNKNOWN이 되어 해당 행이 조회되지 않습니다. NULL 여부를 확인할 때는 반드시 IS NULL 또는 IS NOT NULL을 써야 하며, NULL을 다른 값으로 치환할 때는 표준 함수 COALESCE(컬럼, 대체값)나 Oracle의 NVL(컬럼, 대체값)을 사용합니다.

COUNT(*)는 NULL을 포함하고, COUNT(컬럼)·AVG(컬럼)는 NULL을 뺍니다

4개 행의 보너스(BONUS) 컬럼 값이 각각 100, 200, NULL, 300인 테이블이 있다고 합시다. COUNT(*)는 테이블의 전체 행 수를 세므로 NULL과 상관없이 4를 반환합니다.

반면 COUNT(BONUS), SUM(BONUS), AVG(BONUS)처럼 특정 컬럼을 지정한 집계 함수는 NULL인 행을 먼저 제외하고 계산합니다. 따라서 COUNT(BONUS)는 3이고, AVG(BONUS)는 600÷4(150)가 아니라 NULL을 뺀 3개 행 기준 600÷3 = 200이 됩니다. 만약 NULL을 0점으로 간주한 전체 4명 평균(150)을 구하고 싶다면 AVG(COALESCE(BONUS, 0))으로 작성해야 합니다.

실행 순서와 그룹 조건: WHERE는 그룹화 전, HAVING은 그룹화 후

SELECT 문의 논리적 평가 순서는 FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY입니다.

WHERE 절은 GROUP BY로 묶기 전에 개별 행을 걸러내므로 WHERE 절 안에는 SUM이나 AVG 같은 집계 함수를 직접 적을 수 없습니다. 부서별 평균 급여가 300만 원 이상인 그룹만 남기려면 GROUP BY 뒤에 오는 HAVING AVG(SAL) >= 300 형태로 작성해야 합니다.

작은 두 집합으로 보는 INNER · LEFT · FULL OUTER · CROSS JOIN 건수

왼쪽 테이블 A의 조인 키가 (1, 2, 3) 3행이고, 오른쪽 테이블 B의 조인 키가 (2, 3, 4) 3행일 때(중복 키 없음 가정), 양쪽에 모두 존재하는 키는 (2, 3) 2개뿐입니다. 따라서 INNER JOIN은 매칭된 2행을 반환합니다.

LEFT OUTER JOIN은 왼쪽 A의 (1, 2, 3)을 모두 살리고 B에 없는 1번 행의 오른쪽 컬럼을 NULL로 채워 3행을 반환합니다. FULL OUTER JOIN은 양쪽 합집합인 (1, 2, 3, 4) 4행을, 조인 조건 없는 CROSS JOIN은 가능한 모든 짝(3×3)인 9행을 반환합니다.

한눈에 정리

4행 테이블(값: 100, 200, NULL, 300)과 두 테이블 조인 결과 비교

4행 테이블(값: 100, 200, NULL, 300)과 두 테이블 조인 결과 비교
SQL 구문 / 조인 유형계산 기준결과값 / 행 수핵심 주의점
COUNT(*)NULL 포함 전체 행 수4행 자체의 개수를 셈
COUNT(BONUS)NULL 제외한 컬럼 값 개수3NULL 행은 집계에서 제외
AVG(BONUS)600 ÷ 3 (NULL 제외)200분모가 4가 아니라 3이 됨
AVG(COALESCE(BONUS, 0))(100+200+0+300) ÷ 4150NULL을 0으로 바꾼 뒤 4로 나눔
A(1,2,3) ⋈ B(2,3,4) 조인INNER / LEFT / FULL / CROSS2행 / 3행 / 4행 / 9행일치만(2) / 좌측보존(3) / 양측보존(4) / 곱(9)

직접 풀어보기

예제로 확인하기

01NOT IN 안에 NULL이 포함될 때의 결과 예측

사원 테이블에서 부서번호(DEPT_NO)를 조회할 때 WHERE DEPT_NO NOT IN (10, 20, NULL) 조건을 실행했습니다.

이 쿼리의 조회 결과 행 수는 몇 건인가요?

정답과 풀이 근거
0건 (아무 행도 조회되지 않음)

NOT IN (10, 20, NULL)은 DEPT_NO != 10 AND DEPT_NO != 20 AND DEPT_NO != NULL과 같습니다. 여기서 DEPT_NO != NULL이 항상 UNKNOWN이므로 AND 연산 전체가 참(TRUE)이 될 수 없어 0건이 반환됩니다.

02LEFT OUTER JOIN 결과에서 미매칭 행만 골라내기

고객(CUST, 5명) 테이블과 주문(ORD) 테이블을 고객번호로 LEFT OUTER JOIN 한 뒤, 아직 주문을 한 번도 하지 않은 고객만 찾으려고 합니다.

WHERE 절에 오른쪽 주문 테이블의 기본키(ORD.ORD_ID)를 어떤 조건으로 걸어야 하나요?

정답과 풀이 근거
WHERE ORD.ORD_ID IS NULL

LEFT OUTER JOIN에서 매칭되는 주문이 없는 고객 행은 오른쪽 테이블(ORD)의 모든 컬럼이 NULL로 채워지므로, ORD.ORD_ID IS NULL로 미주문 고객만 추출할 수 있습니다.

마지막 점검

스스로 확인하기

답을 떠올린 뒤 해설을 펼쳐 보세요.

1인수들을 순서대로 확인해 NULL이 아닌 첫 번째 값을 반환하는 ANSI 표준 함수는?
COALESCE

COALESCE(expr1, expr2, ...)는 첫 번째 Non-NULL 값을 반환합니다.

2WHERE 절과 HAVING 절 중 GROUP BY 그룹화 이전에 개별 행을 먼저 필터링하는 절은?
WHERE 절

FROM → WHERE → GROUP BY → HAVING 순서로 실행됩니다.

3왼쪽 기준 테이블의 모든 행은 무조건 출력하고, 오른쪽 테이블에 일치하는 행이 없으면 NULL로 채우는 조인은?
LEFT OUTER JOIN

기준 테이블을 왼쪽에 두고 누락 없이 조회할 때 사용합니다.

4두 SELECT 결과를 합칠 때 중복 제거(정렬) 없이 그대로 이어 붙여 반환하는 집합 연산자는?
UNION ALL

UNION은 중복 행을 제거하고, UNION ALL은 중복 행까지 모두 그대로 반환합니다.

읽기에서 연습으로

이어서 연습하기

SQL NULL·집계·JOIN 카드 10장

규칙 설명 → SQL 용어·함수·절. 본문과 연결된 10개 문항을 순서대로 확인합니다. 카드의 알아요·몰라요는 자기평가이며 같은 뜻의 다른 답도 해설과 비교해 주세요.

SQL NULL·집계·JOIN 카드 10장 시작

아래는 전체 세트의 첫 10개를 여는 넓은 범위 복습입니다. 위의 선별 연습과 시작 문항이 다를 수 있습니다.

전체 메뉴