Burada NOT IN (subquery)null'ları doğru bir şekilde ele almayan ve lehine kaçınılması gereken cevaplardan çıkarılabilir NOT EXISTS. Bununla birlikte, böyle bir sonuç erken olabilir. Aşağıdaki senaryoda, Chris Date (Veritabanı Programlama ve Tasarım, Cilt 2 No 9, Eylül 1989) olarak adlandırılan, NOT INnull'ları doğru şekilde işleyip doğru sonucu döndürmektir NOT EXISTS.
Miktar ( ) olarak parça ( ) sağladığı bilinen sptedarikçileri ( sno) temsil eden bir tablo düşünün . Tablo şu anda aşağıdaki değerleri içermektedir:pnoqty
VALUES ('S1', 'P1', NULL),
('S2', 'P1', 200),
('S3', 'P1', 1000)
Miktarın boş bırakılabilir olduğunu, yani bir tedarikçinin hangi miktarda bilinmese de parça tedarik ettiği bilindiğini kaydedebildiğini unutmayın.
Görev, tedarik parça numarası 'P1' olarak bilinen ancak 1000 miktarında olmayan tedarikçileri bulmaktır.
Aşağıdakiler NOT INyalnızca tedarikçi 'S2'yi doğru bir şekilde tanımlamak için kullanır :
WITH sp AS
( SELECT *
FROM ( VALUES ( 'S1', 'P1', NULL ),
( 'S2', 'P1', 200 ),
( 'S3', 'P1', 1000 ) )
AS T ( sno, pno, qty )
)
SELECT DISTINCT spx.sno
FROM sp spx
WHERE spx.pno = 'P1'
AND 1000 NOT IN (
SELECT spy.qty
FROM sp spy
WHERE spy.sno = spx.sno
AND spy.pno = 'P1'
);
Bununla birlikte, aşağıdaki sorgu aynı genel yapıyı kullanır, ancak NOT EXISTSsonuçta 'S1' tedarikçisini içerir , ancak yanlıştır (yani miktarın boş olduğu):
WITH sp AS
( SELECT *
FROM ( VALUES ( 'S1', 'P1', NULL ),
( 'S2', 'P1', 200 ),
( 'S3', 'P1', 1000 ) )
AS T ( sno, pno, qty )
)
SELECT DISTINCT spx.sno
FROM sp spx
WHERE spx.pno = 'P1'
AND NOT EXISTS (
SELECT *
FROM sp spy
WHERE spy.sno = spx.sno
AND spy.pno = 'P1'
AND spy.qty = 1000
);
Görünen NOT EXISTSgümüş mermi de öyle değil!
Tabii ki, sorunun kaynağı null'ların varlığıdır, bu nedenle 'gerçek' çözüm bu null'ları ortadan kaldırmaktır.
Bu, iki tablo kullanılarak (diğer olası tasarımların yanı sıra) elde edilebilir:
sp yedek parça tedarik ettiği bilinen tedarikçiler
spq bilinen miktarlarda parça tedarik ettiği bilinen tedarikçiler
spqreferansların muhtemelen yabancı bir anahtar kısıtlaması olması gerektiğine dikkat çeker sp.
Sonuç daha sonra 'eksi' ilişkisel operatör ( EXCEPTStandart SQL'deki anahtar kelime olarak) kullanılarak elde edilebilir;
WITH sp AS
( SELECT *
FROM ( VALUES ( 'S1', 'P1' ),
( 'S2', 'P1' ),
( 'S3', 'P1' ) )
AS T ( sno, pno )
),
spq AS
( SELECT *
FROM ( VALUES ( 'S2', 'P1', 200 ),
( 'S3', 'P1', 1000 ) )
AS T ( sno, pno, qty )
)
SELECT sno
FROM spq
WHERE pno = 'P1'
EXCEPT
SELECT sno
FROM spq
WHERE pno = 'P1'
AND qty = 1000;
NOT INbir dizi<> anddeğişikliğe dönüştürmenin bu sette değil anlamsal davranışını başka bir şeye dönüştürdüğüne dikkat çekti mi?