Cú pháp: NOT IN với subquery
SELECT * FROM bang_A WHERE cot_A NOT IN (SELECT cot_B FROM bang_B);
Ví dụ: Bảng A (5 dòng), Bảng B (2 dòng)
Bảng A
+-------+ | Value | +-------+ | 10 | | 20 | | 30 | | 50 | | 80 | +-------+
Bảng B
+--------+ | Value2 | +--------+ | 20 | | 50 | +--------+
Truy vấn
mysql> SELECT * FROM A WHERE Value NOT IN (SELECT Value2 FROM B);
Kết quả (3 dòng: 10, 30, 80)
+-------+ | Value | +-------+ | 10 | | 30 | | 80 | +-------+
⚠️ Cạm bẫy NULL với NOT IN
Nếu subquery trả về NULL, NOT IN sẽ trả về **rỗng** (không phải lỗi, nhưng sai logic):
SELECT * FROM A WHERE Value NOT IN (20, 50, NULL); -- Trả về 0 dòng!
Giải pháp an toàn: NOT EXISTS
SELECT * FROM A WHERE NOT EXISTS (SELECT 1 FROM B WHERE B.Value2 = A.Value);
- Xử lý NULL đúng logic
- Không bị vấn đề "NULL trong danh sách"
Cách khác: LEFT JOIN + IS NULL
SELECT A.* FROM A LEFT JOIN B ON A.Value = B.Value2 WHERE B.Value2 IS NULL;
So sánh
| Cách | Xử lý NULL | Hiệu năng | Độ phức tạp |
|---|---|---|---|
| NOT IN | Sai nếu có NULL | Trung bình | Đơn giản |
| NOT EXISTS | Đúng | Tốt | Trung bình |
| LEFT JOIN IS NULL | Đúng | Tốt | Phức tạp hơn |
Khuyến nghị: Luôn dùng NOT EXISTS hoặc LEFT JOIN ... IS NULL thay vì NOT IN khi subquery có thể trả về NULL.