Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Chuyển đổi KHÔNG VÀO thành KHÔNG TỒN TẠI

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 EXISTSNOT 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 EXISTSNOT 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...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.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Oracle Forms 6i gặp sự cố với 0xC0000005 khi bắt đầu cài đặt bản vá 19

  2. Oracle ODP.net Trình điều khiển được quản lý và Không được quản lý

  3. ORA - 00933 nhầm lẫn với tham gia bên trong và như

  4. Oracle chèn từ select vào bảng với nhiều cột hơn

  5. Định dạng kết quả truy vấn số SQL với một số vị trí thập phân tùy ý