Hãy tưởng tượng bạn đang join hai bảng: students (sinh viên) và enrollments (đăng ký khóa học). Nếu trong bảng enrollments không có thông tin về một sinh viên nào đó, nhưng bạn dùng, ví dụ, LEFT JOIN, thì dòng từ bảng students vẫn sẽ xuất hiện, nhưng thông tin từ enrollments sẽ bị thiếu. Thay vì dữ liệu cụ thể, lúc này sẽ xuất hiện NULL.
Đại khái nó sẽ như thế này:
Bảng students:
| id | name |
|---|---|
| 1 | Eva |
| 2 | Peter |
| 3 | Anna |
Bảng enrollments:
| student_id | course_name |
|---|---|
| 1 | Toán học |
| 1 | Tin học |
| 2 | Vật lý |
Câu truy vấn với LEFT JOIN:
SELECT students.id, students.name, enrollments.course_name
FROM students
LEFT JOIN enrollments ON students.id = enrollments.student_id;
Kết quả:
| id | name | course_name |
|---|---|---|
| 1 | Eva | Toán học |
| 1 | Eva | Tin học |
| 2 | Peter | Vật lý |
| 3 | Anna | NULL |
Chào mừng NULL nhé! Như bạn thấy, với Anna, người không đăng ký bất kỳ khóa học nào, thông tin về khóa học bị thiếu và thay vào đó là NULL.
NULL ảnh hưởng đến truy vấn như thế nào?
NULL — không phải là "số 0" cũng không phải là "chuỗi rỗng", nó là không có giá trị. Kiểu này dẫn đến một số hậu quả thú vị (và đôi khi khá khó chịu):
So sánh với NULL:
Nếu bạn viết kiểu như WHERE course_name = NULL, truy vấn sẽ không trả về dòng nào có NULL. Tại sao? Vì không thể so sánh trực tiếp với NULL.
Để kiểm tra có NULL hay không, phải dùng toán tử đặc biệt:
WHERE course_name IS NULL
Phép toán toán học:
Bất kỳ phép toán nào với NULL đều trả về NULL. Ví dụ:
SELECT 5 + NULL; -- kết quả: NULL
Hàm tổng hợp:
Hầu hết các hàm tổng hợp như SUM(), AVG() sẽ bỏ qua NULL, nhưng COUNT(*) thì vẫn đếm chúng như là "dòng tồn tại".
Làm sao xử lý NULL?
- Thay
NULLbằng giá trị dễ hiểu vớiCOALESCE()
Hàm COALESCE() cho phép thay NULL bằng giá trị khác. Ví dụ, nếu không có khóa học, bạn có thể ghi "Không có khóa học":
SELECT
students.id,
students.name,
COALESCE(enrollments.course_name, 'Không có khóa học') AS course_name
FROM
students LEFT JOIN enrollments
ON students.id = enrollments.student_id;
Kết quả:
| id | name | course_name |
|---|---|---|
| 1 | Eva | Toán học |
| 1 | Eva | Tin học |
| 2 | Peter | Vật lý |
| 3 | Anna | Không có khóa học |
Nhìn ổn hơn nhiều rồi đúng không?
- Lọc bỏ các giá trị
NULL
Nếu bạn không muốn thấy dòng có NULL, hãy dùng điều kiện WHERE ... IS NOT NULL. Ví dụ:
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;
Kết quả:
| id | name | course_name |
|---|---|---|
| 1 | Eva | Toán học |
| 1 | Eva | Tin học |
| 2 | Peter | Vật lý |
Anna biến mất khỏi kết quả vì cô ấy không có đăng ký khóa học nào.
- Đếm có xét đến
NULL: ví dụ vớiCOUNT
Như đã nói ở trên, một số hàm sẽ bỏ qua NULL, một số thì không. Ví dụ:
Để đếm tất cả các dòng, kể cả dòng có NULL:
SELECT COUNT(*) FROM students; -- Đếm TẤT CẢ các dòng (kể cả dòng có `course_name` = NULL)
Để đếm chỉ các dòng không có NULL:
SELECT COUNT(course_name) FROM enrollments;
- Biểu thức điều kiện với
CASE
Nếu bạn không thích COALESCE() hoặc muốn linh hoạt hơn, hãy thử dùng CASE. Ví dụ:
SELECT
students.id,
students.name,
CASE
WHEN enrollments.course_name IS NULL THEN 'Không có khóa học'
ELSE enrollments.course_name
END AS course_name
FROM
students LEFT JOIN enrollments
ON students.id = enrollments.student_id;
Kết quả sẽ giống như khi dùng COALESCE(), nhưng CASE cho phép bạn viết quy tắc phức tạp hơn.
- Dùng
INNER JOINnếu chắc chắn không cóNULL
Cách triệt để nhất để tránh NULL là không cho nó xuất hiện, dùng INNER JOIN. Kiểu join này chỉ trả về dòng có dữ liệu ở cả hai bảng:
SELECT
students.id,
students.name,
enrollments.course_name
FROM
students INNER JOIN enrollments
ON students.id = enrollments.student_id;
Không có bất ngờ gì — chỉ những sinh viên đã đăng ký khóa học mới xuất hiện.
Kết quả:
| id | name | course_name |
|---|---|---|
| 1 | Eva | Toán học |
| 1 | Eva | Tin học |
| 2 | Peter | Vật lý |
Nếu dữ liệu của bạn cần hiển thị tất cả giá trị, kể cả NULL, thì INNER JOIN không phù hợp, nhưng đôi khi vậy là đủ rồi.
GO TO FULL VERSION