MySQL “NOT IN” sorgusu


181

Table1Bir temel sütun değeri başka bir tablo ( Table2) bir sütunda mevcut olmadığı tüm satırları atmak için basit bir sorgu çalıştırmak istedim .

Kullanmayı denedim:

SELECT * FROM Table1 WHERE Table1.principal NOT IN Table2.principal

Bunun yerine bir sözdizimi hatası atıyor. Google arama beni insanların MySQL'in desteklemediğini NOT INve son derece karmaşık bir şeyin kullanılması gerektiğini söylediği forumlara yönlendirdi . Bu doğru mu? Yoksa korkunç bir hata mı yapıyorum?


1
Ve üç tablodan benzer veriler istiyorum. Demek istediğim bir table1 2000 girişe sahip, diğer iki tablo 2 & 3 her biri 500 girişe sahip, hepsinin ortak alanı 'name' var. Tablo2 ve 3'te yer almayan tüm detayları 'isim' bazında nasıl alabiliriz. NOT IN iki kez kullanabilir miyiz, eğer öyleyse ..?

Yanıtlar:


310

IN'yi kullanmak için bir kümeniz olmalıdır, bunun yerine bu sözdizimini kullanın:

SELECT * FROM Table1 WHERE Table1.principal NOT IN (SELECT principal FROM table2)

85
Ne zaman table2.principalolabileceğine dikkat et NULL. Bu durumda NOT INher zaman dönecektir FALSEçünkü NOT INolarak ele alınır <> ALLgibi alt sorgu tüm satırları karşılaştırır hangi Table1.principal <> table2.principalile karşılaştırırken başarısız NULL: Table1.principal <> NULLneden olmaz TRUE. Düzeltmek için: NOT IN (SELECT principal FROM table2 WHERE principal IS NOT NULL).
Basti

4
Yorum için teşekkürler @Basti! Sorgunun neden beklendiği gibi çalışmadığını anlamaya çalışırken çok zaman geçirdim.
gvas

3
'NOT IN' listesinde 'SELECT *' kullanmaktan kaçının. Belirli bir sütun seçmelisiniz. Aksi takdirde bu hatayı alırsınız: stackoverflow.com/questions/14046838/…
Lorien Brune

165

Alt sorgu seçeneği zaten yanıtlanmıştır, ancak birçok durumda LEFT JOINa'nın bunu yapmanın daha hızlı bir yolu olabileceğini unutmayın :

SELECT table1.*
FROM table1 LEFT JOIN table2 ON table2.principal=table1.principal
WHERE table2.principal IS NULL

Tabloların hiçbirinde (SRKR'nin yorumunda olduğu gibi) bulunmadığından emin olmak için birden çok tabloyu kontrol etmek istiyorsanız, bunu kullanabilirsiniz:

SELECT table1.*
FROM table1
LEFT JOIN table2 ON table2.name=table1.name
LEFT JOIN table3 ON table3.name=table1.name
WHERE table2.name IS NULL AND table3.name IS NULL

2
Kendi testlerimde, hem NOT IN& için aynı performansa sahipti LEFT JOIN. Her ikisi de +1
BufferStack

bir kez sorgu bir kez koştu iç DB önbellekleme ne olursa olsun aynı sonuçları almalısınız
Toote

Benim için performans çok daha iyiydi. Yabancı anahtarlar ayarlıyken farklı masalardan geçtim.
Keenora Fluffball

36

NOT IN vs. NOT EXISTS vs. SOL JOIN / MySQL'de NULL

MySQL'in yanı sıra SQL Server dışındaki diğer tüm sistemler , eşleşen değer bulunur bulunmaz optimizasyon LEFT JOIN/IS NULL geri dönme FALSEözelliğine sahiptir ve bu davranışı belgelemekle ilgilenen tek sistemdir. […] MySQL algoritma kullanma HASHve MERGEbirleştirme ANTI JOINyeteneğine sahip olmadığından, yapabileceği tek şeyNESTED LOOPS ANTI JOIN

[...]

Esasen, [ NOT IN] , bu kodların farklı kod dalları tarafından yürütülmesine ve sonuçlarında farklı görünmesine rağmen, LEFT JOIN/ ile tamamen aynı olan / IS NULLkullanılan plandır EXPLAIN. Algoritmalar aslında aynıdır ve sorgular aynı zamanda tamamlanır.

[...]

[Kullanırken performans düşüşü NOT EXISTS] için kesin bir neden söylemek zordur , çünkü bu düşüş doğrusaldır ve her iki alanın endekslendiği sürece veri dağılımına, her iki tablodaki değerlerin sayısına vb. MySQL'de esasen bir iş yapan üç kod parçası olduğundan, sorumlu kodun EXISTSekstra zaman alan bir tür ekstra kontrol yapması mümkündür .

[...]

MySQL her üç yöntemi de bir çeşit yapmak için optimize edebilir NESTED LOOPS ANTI JOIN. […] Ancak, bu üç yöntem üç farklı kod parçası tarafından yürütülen üç farklı plan oluşturur. EXISTSYüklem yürütür kod yaklaşık% 30 daha az etkilidir […]

Bu nedenle MySQL'de eksik değerleri aramanın en iyi yolu bir LEFT JOIN/ IS NULLveya NOT INyerine kullanmaktır NOT EXISTS.

(vurgu eklenmiştir)


7

Ne yazık ki "NOT IN" yan tümcesinin MySql kullanımı ile ilgili bir sorun gibi görünüyor, aşağıdaki ekran çekimi yanlış sonuçlar döndüren alt sorgu seçeneğini gösteriyor:

mysql> show variables like '%version%';
+-------------------------+------------------------------+
| Variable_name           | Value                        |
+-------------------------+------------------------------+
| innodb_version          | 1.1.8                        |
| protocol_version        | 10                           |
| slave_type_conversions  |                              |
| version                 | 5.5.21                       |
| version_comment         | MySQL Community Server (GPL) |
| version_compile_machine | x86_64                       |
| version_compile_os      | Linux                        |
+-------------------------+------------------------------+
7 rows in set (0.07 sec)

mysql> select count(*) from TABLE_A where TABLE_A.Pkey not in (select distinct TABLE_B.Fkey from TABLE_B );
+----------+
| count(*) |
+----------+
|        0 |
+----------+
1 row in set (0.07 sec)

mysql> select count(*) from TABLE_A left join TABLE_B on TABLE_A.Pkey = TABLE_B.Fkey where TABLE_B.Pkey is null;
+----------+
| count(*) |
+----------+
|      139 |
+----------+
1 row in set (0.06 sec)

mysql> select count(*) from TABLE_A where NOT EXISTS (select * FROM TABLE_B WHERE TABLE_B.Fkey = TABLE_A.Pkey );
+----------+
| count(*) |
+----------+
|      139 |
+----------+
1 row in set (0.06 sec)

mysql> 

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.