Pembaruan:
Artikel di blog saya ini menjelaskan perbedaan antara metode secara lebih rinci:
NOT IN
vs.NOT EXISTS
vs.LEFT JOIN / IS NULL
:SQL Server
NOT IN
vs.NOT EXISTS
vs.LEFT JOIN / IS NULL
:PostgreSQL
NOT IN
vs.NOT EXISTS
vs.LEFT JOIN / IS NULL
:Oracle
NOT IN
vs.NOT EXISTS
vs.LEFT JOIN / IS NULL
:MySQL
Ada tiga cara untuk melakukan kueri seperti itu:
-
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 )
Ketika table1.common_id
tidak dapat dibatalkan, semua kueri ini secara semantik sama.
Jika nullable, NOT IN
berbeda, karena IN
(dan, oleh karena itu, NOT IN
) kembalikan NULL
ketika suatu nilai tidak cocok dengan apa pun dalam daftar yang berisi NULL
.
Ini mungkin membingungkan tetapi mungkin menjadi lebih jelas jika kita mengingat sintaks alternatif untuk ini:
common_id = ANY
(
SELECT common_id
FROM table1 t1
)
Hasil dari kondisi ini adalah produk boolean dari semua perbandingan dalam daftar. Tentu saja, satu NULL
nilai menghasilkan NULL
hasil yang membuat seluruh hasil NULL
juga.
Kami tidak pernah bisa mengatakan dengan pasti bahwa common_id
tidak sama dengan apa pun dari daftar ini, karena setidaknya salah satu nilainya adalah NULL
.
Misalkan kita memiliki data ini:
common
--
1
3
table1
--
NULL
1
2
LEFT JOIN / IS NULL
dan NOT EXISTS
akan mengembalikan 3
, NOT IN
akan mengembalikan tidak ada (karena akan selalu dievaluasi menjadi FALSE
atau NULL
).
Di MySQL
, jika pada kolom yang tidak dapat dibatalkan, LEFT JOIN / IS NULL
dan NOT IN
sedikit (beberapa persen) lebih efisien daripada NOT EXISTS
. Jika kolom nullable, NOT EXISTS
adalah yang paling efisien (sekali lagi, tidak banyak).
Di Oracle
, ketiga kueri menghasilkan paket yang sama (sebuah ANTI JOIN
).
Di SQL Server
, NOT IN
/ NOT EXISTS
lebih efisien, karena LEFT JOIN / IS NULL
tidak dapat dioptimalkan ke ANTI JOIN
oleh pengoptimalnya.
Di PostgreSQL
, LEFT JOIN / IS NULL
dan NOT EXISTS
lebih efisien daripada NOT IN
, karena dioptimalkan ke Anti Join
, sedangkan NOT IN
menggunakan hashed subplan
(atau bahkan subplan
biasa jika subquery terlalu besar untuk di-hash)