Quan niệm của bạn rằng họ nên làm cùng một công việc là không đúng. Hãy tưởng tượng tập dữ liệu thử nghiệm này:
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;
Kết quả
ID
---
1
2
3
ID
---
1
1
1
2
2
3
Kết quả của bạn chỉ giống nhau nếu cột bạn đang tìm kiếm là duy nhất.
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;
Mặc dù kết quả là như nhau, nhưng kế hoạch thực hiện thì không. Truy vấn đầu tiên sử dụng IN
có thể sử dụng kết hợp chống bán, có nghĩa là nó biết rằng dữ liệu trong t2 là không cần thiết, vì vậy ngay khi tìm thấy một kết hợp duy nhất, nó có thể ngừng quét để tìm các kết hợp tiếp theo.
Nếu bạn giới hạn bảng thứ hai của mình chỉ có các giá trị duy nhất, thì bạn sẽ thấy cùng một kế hoạch:
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;
Tóm lại, hai truy vấn không phải lúc nào cũng mang lại kết quả giống nhau và không phải lúc nào chúng cũng có cùng một kế hoạch. Nó thực sự phụ thuộc vào Chỉ mục của bạn và độ rộng của dữ liệu / truy vấn của bạn.