EXCEPT
Operatör SQL Server 2005 yılında başlatılmış ancak arasındaki fark nedir NOT IN
ve EXCEPT
?
Aynı şeyi yapıyor mu? Bir örnekle basit bir açıklama istiyorum.
EXCEPT
Operatör SQL Server 2005 yılında başlatılmış ancak arasındaki fark nedir NOT IN
ve EXCEPT
?
Aynı şeyi yapıyor mu? Bir örnekle basit bir açıklama istiyorum.
Yanıtlar:
EXCEPT
Ve arasında iki temel fark vardır NOT IN
.
EXCEPT
DISTINCT
sol taraftaki tablodan sağ taraftaki tabloda görünmeyen değerleri filtreler . Aslında NOT EXISTS
bir DISTINCT
cü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.
NOT IN
DISTINCT
değ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 NULL
filtrelenen değerlerde bir a içeriyorsa NOT IN
, beklenmedik sonuçlar vermesi için boş bir sonuç kümesi döndürülür.
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 EXCEPT
3 satır döndürür .#NewCustomers
#ExistingCustomers
NOT IN
bu farklı filtrelemeyi yapmaz #NewCustomers
ve yinelenen 8 ile 4 satır döndürür .
Şimdi bir de eklerseniz NULL
için #ExistingCustomers
masa, biz tarafından döndürülen aynı sonuçları görmek EXCEPT
ancak NOT IN
boş 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 IN
gerçekten bakmalısınız NOT EXISTS
ve Gail Shaw'ın blogunda ikisi arasında iyi bir karşılaştırma var .
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 IN
birden 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_name
ve 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.
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.