2014-08-28 18 views
6

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ừ.)

+1

"đ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

+2

null không phải là giá trị nhưng không xác định –

Trả lời

3

Nếu NULL ở trong điều kiện NOT IN, thì kết quả sẽ luôn là NULL.

id NOT IN (a, b, c) 

là giống như:

id != a AND id != b AND id != c 

Mọi so sánh với NULL với !=, kết quả sẽ là NULL, vì vậy bạn có kết quả trống.


id IN (a, b, c) 

là giống như

id = a OR id = b OR id = c 

, phải không?

Vì vậy, !(id = a OR id = b OR id = c)id != a AND id != b AND id != c.

+3

'<>' là tiêu chuẩn SQL, nhưng câu trả lời là đúng :) –

+0

Bạn có thể chia sẻ ở đâu bạn thấy rằng 'NOT IN (a, b, c) giống như: id! = a AND id! = b AND id! = c' – cha

+0

@cha Xem chỉnh sửa của tôi. – xdazz

Các vấn đề liên quan