Sử dụng NOT IN() trong MySQL
Để tìm các bản ghi mà giá trị cột không nằm trong một danh sách giá trị cho trước, sử dụng toán tử NOT IN().
Ví dụ minh họa
Tạo bảng DemoTable718:
mysql> CREATE TABLE DemoTable718 (
Id INT,
FirstName VARCHAR(100),
Age INT
);
Query OK, 0 rows affected (0.59 sec)
Chèn dữ liệu:
mysql> INSERT INTO DemoTable718 VALUES(101, 'Chris', 26); Query OK, 1 row affected (0.19 sec) mysql> INSERT INTO DemoTable718 VALUES(102, 'Robert', 24); Query OK, 1 row affected (0.13 sec) mysql> INSERT INTO DemoTable718 VALUES(103, 'David', 27); Query OK, 1 row affected (0.16 sec) mysql> INSERT INTO DemoTable718 VALUES(104, 'Mike', 28); Query OK, 1 row affected (0.19 sec) mysql> INSERT INTO DemoTable718 VALUES(105, 'Sam', 23); Query OK, 1 row affected (0.14 sec)
Xem tất cả bản ghi:
mysql> SELECT * FROM DemoTable718;
+------+-----------+------+ | Id | FirstName | Age | +------+-----------+------+ | 101 | Chris | 26 | | 102 | Robert | 24 | | 103 | David | 27 | | 104 | Mike | 28 | | 105 | Sam | 23 | +------+-----------+------+ 5 rows in set (0.00 sec)
Truy vấn tìm bản ghi KHÔNG có Id trong danh sách (101, 103, 104):
mysql> SELECT * FROM DemoTable718 WHERE Id NOT IN('101', '103', '104');
Kết quả:
+------+-----------+------+ | Id | FirstName | Age | +------+-----------+------+ | 102 | Robert | 24 | | 105 | Sam | 23 | +------+-----------+------+ 2 rows in set (0.00 sec)
Lưu ý quan trọng về NULL
NOT IN có hành vi đặc biệt với NULL:
-- Nếu danh sách chứa NULL, kết quả sẽ rỗng (vì NULL comparison = UNKNOWN) SELECT * FROM table WHERE col NOT IN (1, 2, NULL); -- Trả về 0 dòng! -- Giải pháp: Loại bỏ NULL khỏi danh sách hoặc dùng NOT EXISTS SELECT * FROM table WHERE col NOT IN (SELECT val FROM other_table WHERE val IS NOT NULL);
So sánh NOT IN vs NOT EXISTS
| Đặc điểm | NOT IN | NOT EXISTS |
|---|---|---|
| Xử lý NULL | Vấn đề (trả về rỗng nếu subquery có NULL) | An toàn (NULL không ảnh hưởng) |
| Hiệu suất | Tốt với danh sách nhỏ/cứng | Tốt với subquery phức tạp |
| Cú pháp | Đơn giản | Phức tạp hơn |
Khuyến nghị
- Danh sách giá trị tĩnh, nhỏ: dùng
NOT IN - Subquery hoặc dữ liệu lớn: dùng
NOT EXISTS - Luôn đảm bảo cột so sánh và danh sách cùng kiểu dữ liệu