彼らが同じ仕事をするべきだというあなたの考えは真実ではありません。このデータのテスト セットを想像してみてください:
T1
ID
----
1
2
3
4
5
T2
ID
---
1
1
1
2
2
3
DDL
CREATE TABLE dbo.T1 (ID INT NOT NULL);
INSERT dbo.T1 (ID) VALUES (1), (2), (3), (4), (5);
CREATE TABLE dbo.T2 (ID INT NOT NULL);
INSERT dbo.T2 (ID) VALUES (1), (1), (1), (2), (2), (3);
SELECT *
FROM dbo.T1
WHERE T1.ID IN (SELECT T2.ID FROM dbo.T2);
SELECT T1.*
FROM dbo.T1
INNER JOIN dbo.T2
ON T1.ID = T2.ID;
結果
ID
---
1
2
3
ID
---
1
1
1
2
2
3
検索する列が一意である場合にのみ、結果は同じになります。
CREATE TABLE dbo.T1 (ID INT NOT NULL);
INSERT dbo.T1 (ID) VALUES (1), (2), (3), (4), (5);
CREATE TABLE dbo.T2 (ID INT NOT NULL);
INSERT dbo.T2 (ID) VALUES (1), (2), (3);
SELECT *
FROM dbo.T1
WHERE T1.ID IN (SELECT T2.ID FROM dbo.T2);
SELECT T1.*
FROM dbo.T1
INNER JOIN dbo.T2
ON T1.ID = T2.ID;
結果は同じですが、実行計画は異なります。 IN
を使用した最初のクエリ つまり、t2 のデータが不要であることを認識しているため、単一の一致が見つかるとすぐに、それ以上の一致のスキャンを停止できます。
2 番目のテーブルを一意の値のみを持つように制約すると、同じプランが表示されます:
CREATE TABLE dbo.T1 (ID INT NOT NULL PRIMARY KEY);
INSERT dbo.T1 (ID) VALUES (1), (2), (3), (4), (5);
CREATE TABLE dbo.T2 (ID INT NOT NULL PRIMARY KEY);
INSERT dbo.T2 (ID) VALUES (1), (2), (3);
SELECT *
FROM dbo.T1
WHERE T1.ID IN (SELECT T2.ID FROM dbo.T2);
SELECT T1.*
FROM dbo.T1
INNER JOIN dbo.T2
ON T1.ID = T2.ID;
要約すると、2 つのクエリが常に同じ結果をもたらすとは限らず、常に同じ計画を持つとは限りません。これは、インデックスとデータ/クエリの幅に大きく依存します。