EXCEPT演算子とNOT IN


回答:


29

とには2つの重要な違いがEXCEPTありNOT INます。

を除く

EXCEPTDISTINCT右側のテーブルに表示されない左側のテーブルの値をフィルタリングします。これは、NOT EXISTSwith a DISTINCT句を実行するのと本質的に同じです。

また、2つのテーブル(またはテーブルの列のサブセット)が、クエリの左側と右側に同じ数の列を持っていると想定しています

たとえば、次のことはできません。

SELECT ID, Name FROM TableA
EXCEPT
SELECT ID FROM TableB

これはエラーになります:

UNION、INTERSECT、またはEXCEPT演算子を使用して結合されたすべてのクエリは、ターゲットリストに同数の式を持っている必要があります。

ありませんで

NOT INDISTINCT値をフィルタリングせず、右側のテーブルに表示されない左側のテーブルのすべての値を返します。

NOT IN 1つのテーブルの1つの列を別のテーブルまたはサブクエリの1つの列と比較する必要があります。

たとえば、サブクエリが複数の列を返す場合:

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

次のエラーが表示されます。

サブクエリがEXISTSで導入されていない場合、選択リストに指定できる式は1つだけです。

ただし、右側のテーブルにNULLでフィルタされる値にが含まれている場合NOT IN、空の結果セットが返され、予期しない結果が生じる可能性があります。

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)

上記の2つのクエリEXCEPTから#NewCustomers、から3行を返し、一致する1と3と#ExistingCustomers重複する8を除外します。

NOT INこの個別のフィルタリングは行わず#NewCustomers、重複する8 行から4行を返します。

私たちは今に追加する場合NULL#ExistingCustomers、テーブル、我々はによって返された同じ結果を参照してくださいEXCEPTしかし、NOT IN空の結果セットを返します。

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;

代わりにNOT IN、実際に見てください。GailShawのブログでNOT EXISTSこの2つをよく比較できます。


適切な場合を除き、インデックスを使用しますか?
-JohnOpincar

1

マークシンキンソンの素晴らしいコメントへの追加:

NOT INでは、1つのテーブルの1つの列を別のテーブルまたはサブクエリの1つの列と比較する必要があります。

実際にはNOT IN、複数の列で実行できます。
たとえば、これは完全に合法な* SQLクエリです。

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)

これは戻りますfirst_namelast_name、従業員であるが、管理職ではないすべての人々の。

*:しかし、SQL Serverにはまだ構築が実装されていません。


-2

メインクエリとサブクエリの述語の間に相関関係が必要であるため、上記のNOT INは失敗します。省略した場合、UNCORRELATEDサブクエリが取得されます。

SELECT * FROM TableA AS nc WHERE ID NOT IN(SELECT ID、Name FROM TableB AS ec where nc.ID = ec.ID)

EXCEPTの方が優れており、IS NULL / IS NOT NULL述語を使用せずにNULL行を処理します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.