EXCEPT operatörü vs NOT IN


Yanıtlar:


29

EXCEPTVe arasında iki temel fark vardır NOT IN.

DIŞINDA

EXCEPTDISTINCTsol taraftaki tablodan sağ taraftaki tabloda görünmeyen değerleri filtreler . Aslında NOT EXISTSbir DISTINCTcümle ile yapmakla aynıdır .

Ayrıca, iki tablonun (veya tablolardan sütunların alt kümesinin) sorgunun sol ve sağ tarafında aynı sayıda sütun olmasını bekler

Örneğin, şunları yapamazsınız:

SELECT ID, Name FROM TableA
EXCEPT
SELECT ID FROM TableB

Bu hatayla sonuçlanır:

Bir UNION, INTERSECT veya EXCEPT operatörü kullanılarak birleştirilen tüm sorguların hedef listelerinde eşit sayıda ifade bulunmalıdır.

DEĞİL

NOT INDISTINCTdeğerleri filtrelemez ve sol taraftaki tablodan sağ taraftaki tabloda görünmeyen tüm değerleri döndürür.

NOT IN bir tablodaki tek bir sütunu, başka bir tablodaki veya alt sorgudaki tek bir sütunla karşılaştırmanızı gerektirir.

Örneğin, alt sorgunuz birden çok sütun döndürecekse:

SELECT * FROM TableA AS nc
WHERE ID NOT IN (SELECT ID, Name FROM TableB AS ec)

Aşağıdaki hatayı alırsınız:

Alt sorgu EXISTS ile kullanılmadığında, seçim listesinde yalnızca bir ifade belirtilebilir.

Ancak, sağ taraftaki tablo NULLfiltrelenen değerlerde bir a içeriyorsa NOT IN, beklenmedik sonuçlar vermesi için boş bir sonuç kümesi döndürülür.

MİSAL

CREATE TABLE #NewCustomers (ID INT);
CREATE TABLE #ExistingCustomers (ID INT);

INSERT INTO #NewCustomers
        ( ID )
VALUES
     (8), (9), (10), (1), (3), (8);

INSERT INTO #ExistingCustomers
        ( ID )
VALUES
        ( 1) , (2), (3), (4), (5);


-- EXCEPT filters for DISTINCT values
SELECT * FROM #NewCustomers AS nc
EXCEPT
SELECT * FROM #ExistingCustomers AS ec

-- NOT IN returns all values without filtering
SELECT * FROM #NewCustomers AS nc
WHERE ID NOT IN (SELECT ID FROM #ExistingCustomers AS ec)

Yukarıdaki iki sorgudan, eşleşen 1 ve 3 ve yinelenen 8 filtrelenerek EXCEPT3 satır döndürür .#NewCustomers#ExistingCustomers

NOT INbu farklı filtrelemeyi yapmaz #NewCustomersve yinelenen 8 ile 4 satır döndürür .

Şimdi bir de eklerseniz NULLiçin #ExistingCustomersmasa, biz tarafından döndürülen aynı sonuçları görmek EXCEPTancak NOT INboş bir sonuç kümesi döndürür.

INSERT INTO #ExistingCustomers
        ( ID )
VALUES
        ( NULL );

-- With NULL values in the right-hand table, EXCEPT still returns the same results as above
SELECT * FROM #NewCustomers AS nc
EXCEPT
SELECT * FROM #ExistingCustomers AS ec

-- NOT IN now returns no results
SELECT * FROM #NewCustomers AS nc
WHERE ID NOT IN (SELECT ID FROM #ExistingCustomers AS ec)

DROP TABLE #NewCustomers;
DROP TABLE #ExistingCustomers;

Bunun yerine, NOT INgerçekten bakmalısınız NOT EXISTSve Gail Shaw'ın blogunda ikisi arasında iyi bir karşılaştırma var .


EXCEPT uygunsa endeksleri kullanacak mı?
JohnOpincar

1

Mark Sinkinson'ın mükemmel yorumuna bir katkı:

NOT IN, bir tablodaki tek bir sütunu, başka bir tablodaki veya alt sorgudaki tek bir sütunla karşılaştırmanızı gerektirir.

Aslında, NOT INbirden fazla sütunla gerçekleştirebilirsiniz.
Örneğin, bu bir prefectly yasal * SQL sorgusu:

SELECT  E.first_name, E.last_name
FROM    employees E
WHERE   (E.first_name, E.last_name) NOT IN 
              (SELECT M.first_name, M.last_name FROM managers M)

Hangi dönecektir first_nameve last_nameçalışanları bütün insanların değil, aynı zamanda yöneticileri değil.

*: ancak yapı henüz SQL Server'da uygulanmamıştır.


-2

Yukarıdaki NOT IN başarısız çünkü ana sorgu ve alt sorgu tahminleri arasında bir korelasyon olması gerekir. Dışarıda bırakırsanız, KONTROSİZ bir alt sorgu alırsınız.

SEÇİN * TableA'DAN AS nc NEREDE NEREDE (SEÇİM KİMLİĞİ, TabloB'DEN AD ec olarak nc.ID = ec.ID)

EXCEPT daha iyidir ve IS NULL / IS NOT NULL tahminlerini kullanmadan tüm null satırları işler.

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.