PostgreSQL 'NOT IN' ve alt sorgu


91

Bu sorguyu yürütmeye çalışıyorum:

SELECT mac, creation_date 
FROM logs 
WHERE logs_type_id=11
AND mac NOT IN (select consols.mac from consols)

Ama sonuç alamıyorum. Test ettim ve sözdiziminde bir sorun olduğunu biliyorum. MySQL'de böyle bir sorgu mükemmel çalışır. Tabloda macolmayan bir tane olduğundan emin olmak için bir satır ekledim consols, ancak yine de herhangi bir sonuç vermiyor.


4
consols.mackolon NULLveya NOT NULL?
Mark Byers

Yanıtlar:


169

NOT IN kullanırken değerlerden hiçbirinin NULL olmadığından emin olmalısınız:

SELECT mac, creation_date 
FROM logs 
WHERE logs_type_id=11
AND mac NOT IN (
    SELECT mac
    FROM consols
    WHERE mac IS NOT NULL -- add this
)

4
Not: Her zaman NULL'leri (ve kopyaları) kaldırdığı WHERE mac IS NOT NULLiçin alt sorgudaki cümle gerekli değildir In(...). Çünkü bir küme NULL içeremez
wildplasser

7
@wildplasser Bunu bilmiyorum. Ekleyene kadar benim için çalışmıyordu IS NOT NULL. Yuvalanmış olan SELECTbir kaç kişiyi geri NULLSgetiriyordu ve bu da IN(SELECT...).
robins35

2
Bunun neden IS NOT NULLişe yaradığına dair bir açıklamayı çok takdir ediyorum .
mbarkhau

7
Görünüşe göre cümle NULLiçinde kullanmak NOT INişe yaramıyor çünkü ile karşılaştırma NULLne doğru ne de yanlış. sqlbadpractices.com/using-not-in-operator-with-null-values
mbarkhau

2
Alt sorgu is not nullhiçbir eşleşen değer ve en az bir nulldeğer üretmezse, sorgu hiçbir satır döndürmez . Gönderen bölüm 9.22 "[...] Hiçbir eşit sağ değerler ve en az bir sağ satır verimleri boş DEĞİL yapı İÇİNDE olacak boş bir sonucudur varsa, doğru değil: akım (sürüm 10) PostgreSQL manuel ait . "
Christopher Lewis

29

NOT IN kullanırken, boş vakaları sessizce ele alan NOT EXISTS'i de dikkate almalısınız. Ayrıca bkz. PostgreSQL Wiki

SELECT mac, creation_date 
FROM logs lo
WHERE logs_type_id=11
AND NOT EXISTS (
  SELECT *
  FROM consols nx
  WHERE nx.mac = lo.mac
  );

3
Ayrıca NOT EXISTSvs... NOT IN
IcanDivideBy0

1
@ IcanDivideBy0 Çoğu durumda aynı sorgu planını oluştururlar. Test ettin mi?
wildplasser

1
Alt sorgular durumunda NOT IN yerine NOT IN kullanmanın da bir performans kazanımı vardır. Bkz. Wiki.postgresql.org/wiki/Don%27t_Do_This#Don.27t_use_NOT_IN
Gerbrand

8

Ayrıca LEFT JOIN ve IS NULL koşulunu da kullanabilirsiniz:

SELECT 
  mac, 
  creation_date 
FROM 
  logs
    LEFT JOIN consols ON logs.mac = consols.mac
WHERE 
  logs_type_id=11
AND
  consols.mac IS NULL;

"Mac" sütunlarındaki bir dizin performansı artırabilir.

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.