핵심 짚어보기
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)과 두 테이블 조인 결과 비교
| SQL 구문 / 조인 유형 | 계산 기준 | 결과값 / 행 수 | 핵심 주의점 |
|---|---|---|---|
| COUNT(*) | NULL 포함 전체 행 수 | 4 | 행 자체의 개수를 셈 |
| COUNT(BONUS) | NULL 제외한 컬럼 값 개수 | 3 | NULL 행은 집계에서 제외 |
| AVG(BONUS) | 600 ÷ 3 (NULL 제외) | 200 | 분모가 4가 아니라 3이 됨 |
| AVG(COALESCE(BONUS, 0)) | (100+200+0+300) ÷ 4 | 150 | NULL을 0으로 바꾼 뒤 4로 나눔 |
| A(1,2,3) ⋈ B(2,3,4) 조인 | INNER / LEFT / FULL / CROSS | 2행 / 3행 / 4행 / 9행 | 일치만(2) / 좌측보존(3) / 양측보존(4) / 곱(9) |
직접 풀어보기
예제로 확인하기
01NOT IN 안에 NULL이 포함될 때의 결과 예측
사원 테이블에서 부서번호(DEPT_NO)를 조회할 때 WHERE DEPT_NO NOT IN (10, 20, NULL) 조건을 실행했습니다.
이 쿼리의 조회 결과 행 수는 몇 건인가요?
정답과 풀이 근거
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)를 어떤 조건으로 걸어야 하나요?
정답과 풀이 근거
LEFT OUTER JOIN에서 매칭되는 주문이 없는 고객 행은 오른쪽 테이블(ORD)의 모든 컬럼이 NULL로 채워지므로, ORD.ORD_ID IS NULL로 미주문 고객만 추출할 수 있습니다.
마지막 점검
스스로 확인하기
답을 떠올린 뒤 해설을 펼쳐 보세요.
1인수들을 순서대로 확인해 NULL이 아닌 첫 번째 값을 반환하는 ANSI 표준 함수는?
COALESCE(expr1, expr2, ...)는 첫 번째 Non-NULL 값을 반환합니다.
2WHERE 절과 HAVING 절 중 GROUP BY 그룹화 이전에 개별 행을 먼저 필터링하는 절은?
FROM → WHERE → GROUP BY → HAVING 순서로 실행됩니다.
3왼쪽 기준 테이블의 모든 행은 무조건 출력하고, 오른쪽 테이블에 일치하는 행이 없으면 NULL로 채우는 조인은?
기준 테이블을 왼쪽에 두고 누락 없이 조회할 때 사용합니다.
4두 SELECT 결과를 합칠 때 중복 제거(정렬) 없이 그대로 이어 붙여 반환하는 집합 연산자는?
UNION은 중복 행을 제거하고, UNION ALL은 중복 행까지 모두 그대로 반환합니다.
읽기에서 연습으로
이어서 연습하기
SQL NULL·집계·JOIN 카드 10장
규칙 설명 → SQL 용어·함수·절. 본문과 연결된 10개 문항을 순서대로 확인합니다. 카드의 알아요·몰라요는 자기평가이며 같은 뜻의 다른 답도 해설과 비교해 주세요.
SQL NULL·집계·JOIN 카드 10장 시작아래는 전체 세트의 첫 10개를 여는 넓은 범위 복습입니다. 위의 선별 연습과 시작 문항이 다를 수 있습니다.
SQLD 핵심 객관식 — 데이터 모델링·SQL·JOIN·윈도우 함수
50문항 · 객관식 문제 → 정답·해설 확인
컴활 1급 필기 3과목 데이터베이스 일반 (SQL·정규화·Access 빈출 객관식)
60문항 · 객관식 문제 → 정답·해설 확인