Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

Mengubah NOT IN menjadi NOT EXISTS

Ini agak sederhana, ketika Anda menguasainya:

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);

Baris itu pada dasarnya membandingkan S.S_Id dengan semua e.S_Id nilai yang berasal dari subquery.

Sekarang ubah menjadi NOT EXISTS dan beri tanda centang persamaan S.S_Id = e.S_Id , di dalam subkueri:

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);

Perubahan kecil yang mungkin adalah menyadari bahwa (SELECT e.S_Id ... tidak benar-benar membutuhkan e.S_Id . Subkueri dengan EXISTS dan NOT EXISTS cukup periksa apakah ada baris yang dikembalikan atau tidak dan nilai kolom tidak masalah. Anda dapat menempatkan SELECT * atau konstanta di sana (SELECT 1 umum) atau SELECT NULL atau bahkan SELECT 1/0 (Ya, itu akan berhasil!):

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);

Pertimbangan utama lainnya adalah ketika Anda melakukan konversi dengan cara ini, (tampaknya setara) NOT EXISTS dan NOT IN penulisan kueri benar-benar setara hanya jika keduanya S_Id kolom tidak dapat dibatalkan. Jika e.S_Id kolom nullable, NOT IN dapat mengakibatkan seluruh kueri tidak mengembalikan baris sama sekali (karena x NOT IN (a, b, c, ...) setara dengan x<>a AND x<>b AND ... dan kondisi tersebut tidak mungkin benar jika salah satu dari a,b,c... adalah NULL .)

Untuk alasan yang sama, Anda akan mendapatkan hasil yang berbeda jika s.S_Id is nullable (hal itu tidak mungkin terjadi dalam kasus ini karena mungkin itu adalah kunci utama tetapi dalam kasus lain itu penting.)

Jadi hampir selalu lebih baik menggunakan NOT EXISTS , karena berperilaku berbeda meskipun salah satu kolom tidak dapat dibatalkan (S.S_Id = e.S_Id check akan membuang baris dengan null sebelumnya) dan biasanya perilaku ini yang diinginkan. Ada banyak detail dalam pertanyaan: TIDAK DI vs TIDAK ADA , dalam jawaban oleh @Martin Smith. Anda juga akan menemukan cara untuk mengonversi NOT IN ke NOT EXISTS dan pertahankan perilaku terkait nol (tidak menyenangkan).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. oci_bind_by_name dan to_date PHP/OCI/Oracle

  2. Bagaimana saya bisa mempercepat row_number di Oracle?

  3. Pengecualian PL/SQL pada Perbarui/Hapus baris yang tidak ada

  4. Setel nilai default bidang tabel ORACLE ke formular

  5. Oracle untuk mengambil catatan maksimum