EXCEPT演算子とNOTIN演算子はどちらも、特定の基準に基づいてテーブルからレコードをフィルタリングするために使用されます。この記事では、これらの演算子を詳しく見て、それらの違いを調査します。
先に進む前に、この例で使用するダミーデータを作成しましょう。
ダミーデータの準備
次のスクリプトを実行して、この記事で使用するダミーのデータベースとテーブルを作成します。
CREATE Database ShowRoom; GO USE ShowRoom; CREATE TABLE Cars1 ( id INT, name VARCHAR(50) NOT NULL, company VARCHAR(50) NOT NULL, power INT NOT NULL ) CREATE TABLE Cars2 ( id INT, name VARCHAR(50) NOT NULL, company VARCHAR(50) NOT NULL, power INT NOT NULL )
上記のスクリプトでは、Cars1とCars2の2つのテーブルを使用してShowRoomデータベースを作成します。
Cars1テーブルとCars2テーブルにダミーレコードを追加しましょう。
次のスクリプトを実行します。
USE ShowRoom INSERT INTO Cars1 VALUES (1, 'Corrolla', 'Toyota', 1800), (2, 'City', 'Honda', 1500), (3, 'C200', 'Mercedez', 2000), (4, 'Vitz', 'Toyota', 1300), (5, 'Baleno', 'Suzuki', 1500), (6, 'C500', 'Mercedez', 5000), (7, '800', 'BMW', 8000), (8, 'Mustang', 'Ford', 5000), (9, '208', 'Peugeot', 5400), (10, 'Prius', 'Toyota', 3200) INSERT INTO Cars2 VALUES (6, 'C500', 'Mercedez', 5000), (7, '800', 'BMW', 8000), (8, 'Mustang', 'Ford', 5000), (9, '208', 'Peugeot', 5400), (10, 'Prius', 'Toyota', 3200), (11, 'Atlas', 'Volkswagen', 5000), (12, '110', 'Bugatti', 8000), (13, 'Landcruiser', 'Toyota', 3000), (14, 'Civic', 'Honda', 1800), (15, 'Accord', 'Honda', 2800)
これで、有用なデータセットができました。
このデータを使用して、EXCEPT演算子とNOTIN演算子が互いにどのように異なるかを見てみましょう。
演算子を除く
EXCEPT演算子は、左側のクエリ結果からすべてのレコードをフィルタリングします。これらのレコードは、右側のクエリの結果にも存在し、左側のクエリの残りの結果を返します。
EXCEPT演算子の構文は次のとおりです。
Right_Query EXCEPT Left_Query
EXCEPT演算子を実行する前に満たす必要のある2つの条件があります。それらは:
- 両方のクエリによって返される列の順序と数は同じである必要があります。
- 列のデータ型は一致するか、互換性がある必要があります。
これはトリッキーに聞こえるかもしれません。ただし、次の例で明確になります。
Cars1テーブルとCars2テーブルでは、ID6からID10のレコードが共通です。左側のCars1テーブルと右側のCars2テーブルのレコードでEXCEPT演算子を使用すると、Cars2にないCars1テーブルのレコードが返されます。
EXCEPT演算子の動作を見てみましょう。
USE ShowRoom SELECT id, name, company, power FROM Cars1 Except SELECT id, name, company, power FROM Cars2
上記のクエリの結果は次のようになります:
左側のクエリはCars1テーブルからすべてのレコードを取得し、右側のクエリはCars2テーブルからすべてのレコードを取得します。 Cars1テーブルでは、IDが6から10のレコードもCars2テーブルに存在するため、EXCEPT演算子はCars1テーブルから最初の5行のみを返しました。
同様に、Cars1テーブルに存在しないCars2テーブルからすべてのレコードを返したい場合は、次のクエリに示すように、Cars2テーブルをEXCEPT演算子の左側に移動するだけです。
USE ShowRoom SELECT id, name, company, power FROM Cars2 Except SELECT id, name, company, power FROM Cars1
単一のテーブルでのEXCEPT演算子の使用
前の例では、2つのテーブルにEXCEPT演算子を適用しました。ただし、EXCEPT演算子を使用して、単一のテーブルからレコードをフィルタリングすることもできます。たとえば、電力値が3,000を超えるCars1テーブルのすべてのレコードをフィルタリングする場合は、次のようにEXCEPT演算子を使用できます。
USE ShowRoom SELECT id, name, company, power FROM Cars1 Except SELECT id, name, company, power from Cars1 WHERE power < 3000
上記のスクリプトでは、EXCEPT演算子の左側のクエリは、Cars1テーブルからすべてのレコードを取得します。 EXCEPT演算子の右側のクエリは、電力値が3,000未満のレコードのみをCars1テーブルから取得します。 EXCEPT演算子は、右側のクエリの結果に存在する左側のクエリのレコードをフィルタリングします。したがって、電力が3,000未満のCars1テーブル内のすべてのレコードが除外され、残りのレコードは次の出力に示すように返されます。
オペレーターではありません
NOT IN演算子は、行のフィルタリングにも使用されます。 Cars2テーブルにも存在するCars1テーブルからすべてのレコードを検索し、NOTIN演算子を使用して残りのレコードを返します。
USE ShowRoom SELECT id, name, company, power FROM Cars1 WHERE id NOT IN (SELECT id from Cars2)
上記のクエリの結果は次のようになります:
これは、EXCEPT演算子を使用して得られた結果と似ています。
EXCEPT演算子とNOTIN演算子の違い
EXCEPT演算子とNOTIN演算子を使用して得られた結果は類似していることがわかります。ただし、EXCEPT演算子とNOTIN演算子には2つの大きな違いがあります。
1-NOT INは重複レコードを返しますが、EXCEPTは個別レコードのみを返します
EXCEPT演算子は、結果から重複する行を削除し、DISTINCTレコードのみを返します。一方、NOT IN演算子は重複したレコードを返します。
例を使用して、これを見てみましょう。次のクエリを実行して、Cars1テーブルに重複するレコードを挿入します。
INSERT INTO Cars1 VALUES (1, 'Corrolla', 'Toyota', 1800)
これで、Cars1テーブルに2つの重複レコードがあります。これを確認するには、次のクエリを実行します。
SELECT * FROM Cars1
Cars1テーブルは次のようになります:
行1と11が互いに重複していることがわかります。
まず、EXCEPT演算子を使用して、Cars2テーブルに存在するCars1テーブルのすべてのレコードをフィルタリングしましょう。
USE ShowRoom SELECT id, name, company, power FROM Cars1 Except SELECT id, name, company, power FROM Cars2
結果は次のようになります:
行1と11はCars1テーブルで重複しており、Cars2テーブルには存在しませんでしたが、EXCEPT演算子はこれらの行の両方を返しませんでした。個別の行のみが返されました。
次に、同じタスクにNOTIN演算子を使用しましょう。
USE ShowRoom SELECT id, name, company, power FROM Cars1 WHERE id NOT IN (SELECT id from Cars2)
上記のクエリの出力は次のようになります:
NOT INが重複する行、つまり行1と行6を返すことがわかります。
2-EXCEPTは列を比較し、NOTINは単一の値を比較します
EXCEPT演算子は、1つまたは複数の列の値を比較します。これは、列の数が同じでなければならないことを意味します。一方、NOT IN演算子は、単一の列の値を比較します。
たとえば、次の例に示すように、EXCEPT演算子の左右のクエリに異なる数の列を含めることはできません。
USE ShowRoom SELECT id, name, company, power FROM Cars1 Except SELECT id, name,power FROM Cars2
上記のクエリは次のエラーを返します:
NOT IN演算子の場合、サブクエリに複数の列を含めることはできません。これは、次のクエリがエラーを返すことを意味します:
USE ShowRoom SELECT id, name, company, power FROM Cars1 WHERE id NOT IN (SELECT id, name from Cars2)
上記のスクリプトでは、サブクエリには2つの列(idとname)があります。したがって、エラーがスローされます:
参考資料:
- W3 Schools:INとNOTINの例
- TechontheNet:オペレーターを除く
- YouTube:オペレーターを除く