Nó khá đơn giản, khi bạn hiểu rõ về nó:
SELECT s.S_Fname, s.S_Lname
FROM STUDENT s
WHERE s.S_Sex = 'F'
AND S.S_Id NOT IN(SELECT e.S_Id -- take this line
FROM ENROLLMENT e
WHERE e.Mark < 70);
Về cơ bản dòng đó so sánh S.S_Id
với tất cả e.S_Id
giá trị đến từ truy vấn con.
Bây giờ thay đổi điều đó thành NOT EXISTS
và đặt một kiểm tra bình đẳng S.S_Id = e.S_Id
, bên trong truy vấn con:
SELECT s.S_Fname, s.S_Lname
FROM STUDENT s
WHERE s.S_Sex = 'F'
AND NOT EXISTS (SELECT e.S_Id
FROM ENROLLMENT e
WHERE (e.Mark < 70) -- if this is complex, you'll need parentheses
AND S.S_Id = e.S_Id);
Thay đổi nhỏ có thể xảy ra là nhận ra rằng (SELECT e.S_Id ...
không thực sự cần e.S_Id
. Truy vấn con với EXISTS
và NOT EXISTS
chỉ cần kiểm tra xem có hàng được trả về hay không và giá trị cột không quan trọng. Bạn có thể đặt SELECT *
hoặc một hằng số ở đó (SELECT 1
là phổ biến) hoặc SELECT NULL
hoặc thậm chí SELECT 1/0
(Có, điều đó sẽ hoạt động!):
SELECT s.S_Fname, s.S_Lname
FROM STUDENT s
WHERE s.S_Sex = 'F'
AND NOT EXISTS (SELECT 1
FROM ENROLLMENT e
WHERE e.Mark < 70
AND S.S_Id = e.S_Id);
Một điểm đáng lưu ý khác là khi bạn thực hiện chuyển đổi theo cách này, (có vẻ tương đương) NOT EXISTS
và NOT IN
các văn bản của một truy vấn chỉ thực sự tương đương nếu cả hai S_Id
các cột không thể null. Nếu e.S_Id
cột không có giá trị, NOT IN
có thể dẫn đến toàn bộ truy vấn trả về không có hàng nào cả (bởi vì x NOT IN (a, b, c, ...)
tương đương với x<>a AND x<>b AND ...
và điều kiện đó không thể đúng khi một trong các a,b,c...
là NULL
.)
Vì những lý do tương tự, bạn sẽ có kết quả khác nếu s.S_Id
là nullable (điều đó không có khả năng xảy ra trong trường hợp này vì nó có thể là khóa chính nhưng trong các trường hợp khác, nó quan trọng.)
Vì vậy, hầu như luôn tốt hơn nếu sử dụng NOT EXISTS
, vì nó hoạt động khác nhau ngay cả khi một trong hai cột là giá trị rỗng (S.S_Id = e.S_Id
kiểm tra sẽ loại bỏ các hàng có null trước đó) và thông thường hành vi này là hành vi mong muốn. Có nhiều chi tiết trong câu hỏi: KHÔNG CÓ VÀ KHÔNG TỒN TẠI
, trong câu trả lời của @Martin Smith. Bạn cũng sẽ thấy có nhiều cách để chuyển đổi NOT IN
thành NOT EXISTS
và giữ nguyên hành vi có liên quan (khó chịu) vô hiệu.