Tôi có hai bảng:Tại sao không IN luôn truy xuất cùng một kết quả như MINUS trong Oracle?
CREATE TABLE test1
(id int);
CREATE TABLE test2
(id int);
INSERT INTO test1
VALUES (1);
INSERT INTO test1
VALUES (2);
INSERT INTO test2
VALUES (1);
Sau đó, tôi muốn nhìn thấy một danh sách tất cả các id có trong test1 và test2 không.
Có ít nhất ba cách tôi có thể nghĩ ra để làm điều này:
OUTER JOIN:
SELECT a.id
FROM test1 a LEFT OUTER JOIN test2 b
ON a.id = b.id
WHERE b.id IS NULL;
TRỪ:
SELECT id
FROM test1
MINUS
SELECT id
FROM test2;
NOT IN:
SELECT id
FROM test1
WHERE id NOT IN (
SELECT id
FROM test2
);
Cho đến nay, rất tốt. Tất cả ba truy vấn này sẽ cho tôi kết quả tương tự: 1 hàng, với giá trị 2.
Nếu tôi chèn null vào test2, thì truy vấn OUTER JOIN và MINUS tiếp tục trả về cùng kết quả, nhưng KHÔNG IN mang lại không có hàng.
Điều này làm tôi bối rối. Sau đó, tôi nhận thấy rằng nếu tôi thay đổi nó thành
SELECT id
FROM test1
WHERE id NOT IN (
SELECT id
FROM test2
WHERE id IS NOT NULL
);
tôi nhận được kết quả tôi mong đợi - một hàng một lần nữa.
Tại sao điều này xảy ra? Tôi cho rằng đây là điều khá cơ bản với SQL, nhưng tôi không rõ nó là gì (và tôi khá chắc chắn rằng trong các cơ sở dữ liệu khác mà tôi đã sử dụng trước đó, ba phương pháp mà tôi đã liệt kê đã cho kết quả tương đương - mặc dù tôi không không có SQL Server hoặc postgres để kiểm tra ngay bây giờ, vì vậy tôi có thể là misremembering hành vi của họ).
(Tôi cho rằng một câu trả lời là "Đừng lo lắng và không sử dụng NOT IN" nhưng điều đó có thể tốn kém về khả năng đọc mã - đôi khi thanh lịch hơn làm tất cả mọi thứ với kết nối bên ngoài hoặc trừ.)
"điều gì đó khá cơ bản đối với SQL": Chắc chắn. 'NULL' không bao giờ làm bạn tốt trong so sánh. 'NULL' không bằng nhau hay không bằng bất cứ thứ gì, thậm chí không phải chính nó. – Thilo
null không phải là giá trị nhưng không xác định –