Cập nhật:
Những bài viết trong blog của tôi mô tả sự khác biệt giữa các phương pháp chi tiết hơn:
Có ba cách để thực hiện một truy vấn như vậy:
LEFT JOIN / IS NULL
:
SELECT *
FROM common
LEFT JOIN
table1 t1
ON t1.common_id = common.common_id
WHERE t1.common_id IS NULL
NOT EXISTS
:
SELECT *
FROM common
WHERE NOT EXISTS
(
SELECT NULL
FROM table1 t1
WHERE t1.common_id = common.common_id
)
NOT IN
:
SELECT *
FROM common
WHERE common_id NOT IN
(
SELECT common_id
FROM table1 t1
)
Khi table1.common_id
không thể rỗng, tất cả các truy vấn này đều giống nhau về mặt ngữ nghĩa.
Khi nó là null, NOT IN
thì khác, vì IN
(và, do đó, NOT IN
) trả về NULL
khi một giá trị không khớp với bất cứ thứ gì trong danh sách chứa a NULL
.
Điều này có thể gây nhầm lẫn nhưng có thể trở nên rõ ràng hơn nếu chúng ta nhớ lại cú pháp thay thế cho điều này:
common_id = ANY
(
SELECT common_id
FROM table1 t1
)
Kết quả của điều kiện này là một sản phẩm boolean của tất cả các so sánh trong danh sách. Tất nhiên, một NULL
giá trị duy nhất mang lại NULL
kết quả cũng thể hiện toàn bộ kết quả NULL
.
Chúng tôi không bao giờ không thể nói chắc chắn rằng common_id
nó không bằng bất cứ thứ gì trong danh sách này, vì ít nhất một trong các giá trị là NULL
.
Giả sử chúng ta có những dữ liệu này:
common
--
1
3
table1
--
NULL
1
2
LEFT JOIN / IS NULL
và NOT EXISTS
sẽ trở lại 3
, NOT IN
sẽ trở lại không có gì (vì nó sẽ luôn luôn đánh giá cho một trong hai FALSE
hoặc NULL
).
Trong MySQL
trường hợp trên cột không nullable LEFT JOIN / IS NULL
và NOT IN
hiệu quả hơn một chút (vài phần trăm) so với NOT EXISTS
. Nếu cột là nullable, NOT EXISTS
là hiệu quả nhất (một lần nữa, không nhiều).
Trong Oracle
, cả ba truy vấn đều có cùng một kế hoạch (an ANTI JOIN
).
Trong SQL Server
, NOT IN
/ NOT EXISTS
là hiệu quả hơn, vì LEFT JOIN / IS NULL
không thể được tối ưu hóa thành một ANTI JOIN
bởi trình tối ưu hóa của nó.
Trong PostgreSQL
, LEFT JOIN / IS NULL
và NOT EXISTS
có hiệu quả hơn NOT IN
, sin họ được tối ưu hóa để một Anti Join
, trong khi NOT IN
sử dụng hashed subplan
(hoặc thậm chí là một đồng bằng subplan
nếu subquery là quá lớn để băm)