예를 들어, 두 개의 테이블 students(학생들)랑 enrollments(수강신청 기록)를 합친다고 해보자. 만약 enrollments 테이블에 어떤 학생에 대한 정보가 없는데, 예를 들어 LEFT JOIN을 쓰면, students 테이블의 행은 그대로 나오지만 enrollments의 정보는 빠진다. 이런 경우에 구체적인 데이터 대신 NULL이 뜨게 돼.
대충 이런 식이야:
students 테이블:
| id | name |
|---|---|
| 1 | Eva |
| 2 | Peter |
| 3 | Anna |
enrollments 테이블:
| student_id | course_name |
|---|---|
| 1 | 수학 |
| 1 | 정보학 |
| 2 | 물리 |
LEFT JOIN 쿼리 예시:
SELECT students.id, students.name, enrollments.course_name
FROM students
LEFT JOIN enrollments ON students.id = enrollments.student_id;
결과:
| id | name | course_name |
|---|---|---|
| 1 | Eva | 수학 |
| 1 | Eva | 정보학 |
| 2 | Peter | 물리 |
| 3 | Anna | NULL |
자, NULL 등장! 보다시피, Anna는 아무 과목도 신청 안 했으니까, course 정보가 없어서 NULL로 나와.
NULL이 쿼리에 미치는 영향은?
NULL은 "0"도 아니고 "빈 문자열"도 아니야. 값이 없음을 의미하지. 이게 몇 가지 흥미롭고(가끔 짜증나는) 결과를 가져와:
NULL과 비교:
만약 WHERE course_name = NULL 이런 식으로 쓰면, NULL이 있는 행은 안 나와. 왜냐면 NULL이랑 직접 비교는 안 되거든.
NULL이 있는지 확인하려면 특별한 연산자를 써야 해:
WHERE course_name IS NULL
수학 연산:
NULL이랑 연산하면 무조건 NULL이 나와. 예를 들면:
SELECT 5 + NULL; -- 결과: NULL
집계 함수:
SUM(), AVG() 같은 대부분의 집계 함수는 NULL을 무시하지만, COUNT(*)는 "존재하는 행"으로 세.
NULL 어떻게 다루지?
COALESCE()로NULL을 알아보기 쉬운 값으로 바꾸기
COALESCE() 함수는 NULL을 다른 값으로 바꿔줘. 예를 들어, 과목이 없으면 "과목 없음"으로 표시할 수 있어:
SELECT
students.id,
students.name,
COALESCE(enrollments.course_name, '과목 없음') AS course_name
FROM
students LEFT JOIN enrollments
ON students.id = enrollments.student_id;
결과:
| id | name | course_name |
|---|---|---|
| 1 | Eva | 수학 |
| 1 | Eva | 정보학 |
| 2 | Peter | 물리 |
| 3 | Anna | 과목 없음 |
이제 훨씬 보기 좋지?
NULL값 필터링하기
NULL이 있는 행을 보고 싶지 않으면 WHERE ... IS NOT NULL 조건을 쓰면 돼. 예를 들면:
SELECT
students.id,
students.name,
enrollments.course_name
FROM
students LEFT JOIN enrollments
ON students.id = enrollments.student_id
WHERE
enrollments.course_name IS NOT NULL;
결과:
| id | name | course_name |
|---|---|---|
| 1 | Eva | 수학 |
| 1 | Eva | 정보학 |
| 2 | Peter | 물리 |
Anna는 결과에서 사라져. 왜냐면 수강신청 기록이 없으니까.
NULL을 고려해서 세기:COUNT예시
아까 말했듯이, 어떤 함수는 NULL을 무시하고, 어떤 건 안 그래. 예를 들어:
모든 행을 세고 싶으면, NULL이 있어도:
SELECT COUNT(*) FROM students; -- 모든 행을 셈 (`course_name`이 NULL이어도)
NULL이 없는 행만 세고 싶으면:
SELECT COUNT(course_name) FROM enrollments;
CASE로 조건부 표현식 쓰기
COALESCE()가 마음에 안 들거나 좀 더 유연하게 하고 싶으면 CASE를 써봐. 예를 들면:
SELECT
students.id,
students.name,
CASE
WHEN enrollments.course_name IS NULL THEN '과목 없음'
ELSE enrollments.course_name
END AS course_name
FROM
students LEFT JOIN enrollments
ON students.id = enrollments.student_id;
결과는 COALESCE() 썼을 때랑 똑같아. 근데 CASE는 더 복잡한 규칙도 쓸 수 있지.
NULL이 없다고 확신할 때는INNER JOIN쓰기
NULL을 완전히 피하고 싶으면, 그냥 INNER JOIN을 써서 아예 안 나오게 할 수도 있어. 이 join 타입은 두 테이블에 모두 매칭되는 행만 반환해:
SELECT
students.id,
students.name,
enrollments.course_name
FROM
students INNER JOIN enrollments
ON students.id = enrollments.student_id;
놀랄 일 없음 — 과목 신청한 학생만 나와.
결과:
| id | name | course_name |
|---|---|---|
| 1 | Eva | 수학 |
| 1 | Eva | 정보학 |
| 2 | Peter | 물리 |
만약 네 데이터가 NULL도 다 보여줘야 한다면 INNER JOIN은 안 맞지만, 가끔은 이게 딱이야.
GO TO FULL VERSION