SQL에서 결측처럼 보이는 값이 있다고 해서 전부 NULL인 것은 아니다. 실제 데이터에서는 NULL 대신 빈 문자열('') 로 들어간 경우가 생각보다 자주 나온다. 그래서 필터링 전에 값을 직접 확인하지 않으면, 분명 등급 없는 데이터를 제외했다고 생각했는데 결과가 이상하게 남아 있는 상황이 생긴다.
이 문제는 특히 범주형 컬럼을 다룰 때 자주 나온다. 예를 들어 콘텐츠 데이터의 age_certification처럼 연령 등급이 들어가는 컬럼은 값이 없을 때 NULL일 수도 있고, 빈 문자열일 수도 있고, 심지어 공백 문자열일 수도 있다. 그래서 분석 전에 먼저 해야 할 일은 **“결측처럼 보이는 값이 실제로 어떤 형태로 저장돼 있는지 확인하는 것”**이다.
NULL과 빈 문자열은 왜 다를까
SQL에서 NULL은 “값이 없음”을 의미한다.
반면 빈 문자열 ''은 길이가 0인 문자열 값이다. 즉 둘은 겉으로 보면 둘 다 비어 보일 수 있지만, SQL 입장에서는 완전히 다른 값이다.
이 차이 때문에 아래 두 조건은 같은 의미가 아니다.
WHERE age_certification IS NULL
WHERE age_certification = ''
첫 번째는 실제로 값이 비어 있는 경우만 찾고,
두 번째는 문자열 값은 존재하지만 그 내용이 비어 있는 경우만 찾는다.
즉, 데이터에 따라 둘 중 하나만 써서는 결측처럼 보이는 값을 다 잡지 못할 수 있다.
왜 이 문제가 자주 생기나
CSV, 수집 데이터, 외부 API, 수동 정제 과정을 거친 데이터는 결측 표현 방식이 제각각인 경우가 많다. 어떤 시스템은 값이 없으면 NULL로 저장하고, 어떤 시스템은 빈 문자열로 저장한다. 사용자는 둘 다 “비어 있음”으로 보지만, SQL은 그렇게 처리하지 않는다.
그래서 분석을 시작할 때 바로 필터를 쓰기보다, 먼저 아래 질문을 확인하는 게 안전하다.
- 이 컬럼은 실제로 NULL이 들어가 있나
- 아니면 빈 문자열이 들어가 있나
- 둘 다 섞여 있나
- 공백이 들어간 값은 없나
즉 결측 처리 방식부터 먼저 보는 습관이 중요하다.
값 종류는 먼저 DISTINCT로 확인하는 게 좋다
가장 먼저 할 일은 이 컬럼에 어떤 값들이 들어 있는지 직접 보는 것이다.
SELECT DISTINCT age_certification
FROM titles;
이 쿼리는 age_certification에 어떤 값 종류가 있는지 보여준다.
이 단계에서 실제 데이터에
- PG
- R
- TV-MA
- NULL
- ''
같은 값이 어떻게 섞여 있는지 감이 잡힌다.
즉 DISTINCT는 단순 조회가 아니라, 필터링 전략을 정하기 전에 상태를 점검하는 쿼리라고 보면 된다.
NULL 여부는 IS NULL로 확인한다
NULL은 등호(=)로 비교하지 않는다. NULL 확인은 반드시 IS NULL 또는 IS NOT NULL을 써야 한다.
SELECT *
FROM titles
WHERE age_certification IS NULL;
이 쿼리는 age_certification이 실제 NULL인 행만 조회한다.
여기서 중요한 건, 빈 문자열은 이 조건에 걸리지 않는다는 점이다.
즉 결과가 없다고 해서 “등급 없는 데이터가 없다”라고 결론 내리면 안 된다.
단지 NULL 형태로 저장된 값이 없는 것일 수 있다.
빈 문자열은 = ’’로 확인한다
문자열 컬럼이 비어 있는 경우는 보통 아래처럼 확인한다.
SELECT *
FROM titles
WHERE age_certification = '';
이 쿼리는 값이 NULL은 아니지만, 문자열 내용이 비어 있는 행을 찾는다.
실무에서 많이 헷갈리는 포인트가 바로 여기다.
IS NULL 결과가 안 나와서 문제없다고 생각했는데, 실제로는 ''가 많이 들어 있어서 필터링이 꼬이는 경우가 흔하다.
즉 IS NULL과 = ''는 거의 세트로 확인하는 편이 좋다.
등급 없는 데이터를 제외할 때 흔한 실수
예를 들어 영화 데이터에서 연령 등급별 개수를 집계한다고 해보자.
이때 “등급 없는 데이터는 제외”하려고 아래처럼 쓰는 경우가 많다.
WHERE age_certification IS NOT NULL
문제는 데이터가 NULL이 아니라 빈 문자열로 들어 있다면, 이 조건만으로는 등급 없는 데이터가 여전히 남는다.
반대로 아래처럼만 쓰는 것도 완전하지 않을 수 있다.
WHERE age_certification != ''
이 조건은 빈 문자열은 걸러내지만, NULL 비교는 예상과 다르게 동작할 수 있다.
즉 결측 방식이 혼합돼 있다면 둘 다 고려해야 한다.
실전에서는 이렇게 필터링하는 게 안전하다
age_certification이 비어 있는 값을 제외하고, 영화만 대상으로 연령 등급 Top 5를 보고 싶다면 아래처럼 쓰는 방식이 실전에서 더 안전하다.
SELECT
age_certification,
COUNT(1) AS Cnt
FROM titles
WHERE age_certification != ''
AND type = 'MOVIE'
GROUP BY age_certification
ORDER BY Cnt DESC
LIMIT 5;
이 쿼리는 가이드 기준으로는 빈 문자열을 제외하고 영화만 대상으로 집계하는 방식이다.
다만 실제 데이터에서 NULL까지 함께 존재할 가능성이 있다면, 아래처럼 조건을 더 명시적으로 쓰는 것도 좋다.
SELECT
age_certification,
COUNT(1) AS Cnt
FROM titles
WHERE age_certification IS NOT NULL
AND age_certification != ''
AND type = 'MOVIE'
GROUP BY age_certification
ORDER BY Cnt DESC
LIMIT 5;
즉 핵심은 문법 하나를 외우는 게 아니라,
현재 데이터가 NULL 중심인지, 빈 문자열 중심인지 확인한 뒤 조건을 정하는 것이다.
NULL과 빈 문자열을 같이 볼 때 체크할 것
실무에서 이 문제를 빠르게 점검하려면 아래 순서로 보면 된다.
1) 값 종류 확인
SELECT DISTINCT age_certification
FROM titles;
2) NULL 개수 확인
SELECT COUNT(1)
FROM titles
WHERE age_certification IS NULL;
3) 빈 문자열 개수 확인
SELECT COUNT(1)
FROM titles
WHERE age_certification = '';
이렇게 먼저 점검하면, 이후 집계나 필터링에서 어떤 조건을 써야 하는지 훨씬 명확해진다.
왜 이게 데이터 분석에서 중요하냐
이 문제는 단순한 SQL 문법 차이로 끝나지 않는다.
결측 처리 방식을 잘못 이해하면 아래 같은 문제가 생긴다.
- 연령 등급 분포가 왜곡됨
- 특정 범주 개수가 실제보다 크게 나옴
- “값 없는 데이터는 제외했다”는 가정이 틀림
- 후속 분석 결과가 전부 어긋남
즉 데이터 분석에서 NULL과 빈 문자열 구분은 선택이 아니라 기본 검증 단계에 가깝다.
특히 범주형 컬럼은 한 번 집계해버리면 결과만 보고는 원인을 놓치기 쉬워서, 집계 전에 결측 표현 방식부터 확인하는 것이 중요하다.
실전에서 자주 하는 실수
1) IS NULL만 쓰고 끝내는 경우
결측처럼 보여도 실제론 빈 문자열일 수 있다. 이 경우 NULL만 확인하면 데이터가 남는다.
2) != ''만 쓰고 끝내는 경우
빈 문자열은 제외되지만, NULL 처리까지 충분히 고려하지 못할 수 있다.
3) DISTINCT 없이 바로 집계하는 경우
컬럼 상태를 확인하지 않고 바로 GROUP BY로 가면, 이상한 값이 왜 남는지 뒤늦게 찾게 된다.
4) 공백 문자열을 놓치는 경우
어떤 데이터는 ''가 아니라 ' '처럼 공백으로 들어 있을 수도 있다.
이 경우엔 TRIM() 같은 정제 함수까지 검토해야 한다.
정리
SQL에서 NULL과 빈 문자열은 둘 다 비어 보일 수 있지만, 실제로는 완전히 다른 값이다. 그래서 범주형 컬럼을 분석할 때는 바로 필터를 거는 것보다 먼저 값 종류를 확인하고, IS NULL과 = ''를 각각 점검해야 한다.
특히 age_certification 같은 컬럼은 등급 없는 데이터를 제외했다고 생각해도, 결측 표현 방식이 다르면 결과가 달라질 수 있다. 결국 중요한 건 특정 문법을 외우는 게 아니라, 이 컬럼에서 결측이 어떤 형태로 저장돼 있는지 먼저 확인하는 것이다.
SQL에서 결측처럼 보이는 값은 전부 NULL이 아니다. 분석 전에 IS NULL과 빈 문자열('')을 따로 확인하는 습관이 필요하다.
'Data Analytics > SQL' 카테고리의 다른 글
| MySQL CSV 파일 넣기 | LOAD DATA LOCAL INFILE 사용법과 오류 체크 (0) | 2026.05.26 |
|---|---|
| SQL CASE WHEN + LIKE 정리 | 리뷰 데이터에서 키워드 언급 수 세기 (0) | 2026.05.26 |
| SQL 서브쿼리 주의점 | 최고값 비교할 때 조건 범위를 맞춰야 하는 이유 (0) | 2026.05.26 |
| SQL JOIN으로 N:M 관계 풀기 | 학생-동아리 연결 테이블 예제 (0) | 2026.05.20 |
| SQL INNER JOIN과 LEFT JOIN 차이 | 기준 테이블에 따라 결과가 달라지는 이유 (0) | 2026.05.20 |
