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 IN
null'ları doğru şekilde işleyip doğru sonucu döndürmektir NOT EXISTS
.
Miktar ( ) olarak parça ( ) sağladığı bilinen sp
tedarikçileri ( sno
) temsil eden bir tablo düşünün . Tablo şu anda aşağıdaki değerleri içermektedir:pno
qty
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 IN
yalnı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 EXISTS
sonuç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 EXISTS
gü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
spq
referansların muhtemelen yabancı bir anahtar kısıtlaması olması gerektiğine dikkat çeker sp
.
Sonuç daha sonra 'eksi' ilişkisel operatör ( EXCEPT
Standart 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 IN
bir dizi<> and
değ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?