Memperbarui:
Artikel-artikel ini di blog saya menjelaskan perbedaan antara metode-metode ini secara lebih rinci:
Ada tiga cara untuk melakukan permintaan 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.
Ketika nullable, NOT IN
berbeda, karena IN
(dan, karenanya, NOT IN
) kembali NULL
ketika nilai tidak cocok dengan apa pun dalam daftar yang berisi a 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, NULL
nilai tunggal menghasilkanNULL
hasil yang menjadikan keseluruhan hasil NULL
juga.
Kita tidak pernah bisa mengatakan hal itu dengan pasti common_id
itu tidak sama dengan apa pun dari daftar ini, karena setidaknya salah satu nilainya NULL
.
Misalkan kita memiliki data ini:
common
--
1
3
table1
--
NULL
1
2
LEFT JOIN / IS NULL
dan NOT EXISTS
akan kembali 3
, tidak NOT IN
akan mengembalikan apa pun (karena akan selalu dievaluasi jugaFALSE
atau NULL
).
Dalam MySQL
, dalam kasus pada kolom non-nullable, LEFT JOIN / IS NULL
dan NOT IN
sedikit (beberapa persen) lebih efisien daripadaNOT EXISTS
. Jika kolom dapat dibatalkan, NOT EXISTS
apakah yang paling efisien (sekali lagi, tidak banyak).
Dalam Oracle
, ketiga pertanyaan menghasilkan rencana yang sama (aANTI JOIN
).
Di SQL Server
, NOT IN
/ NOT EXISTS
lebih efisien, karena LEFT JOIN / IS NULL
tidak dapat dioptimalkan keANTI JOIN
oleh pengoptimalnya.
Di PostgreSQL
, LEFT JOIN / IS NULL
dan NOT EXISTS
lebih efisien daripada NOT IN
, mereka dioptimalkan untuk Anti Join
, sementara NOT IN
menggunakan hashed subplan
(atau bahkan dataran subplan
jika subquery terlalu besar untuk hash)