Din forestilling om, at de burde gøre det samme arbejde, er ikke sand. Forestil dig dette testsæt af data:
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;
Resultater
ID
---
1
2
3
ID
---
1
1
1
2
2
3
Dine resultater er kun de samme, hvis kolonnen du søger i er unik.
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;
Selvom resultaterne er de samme, er udførelsesplanen det ikke. Den første forespørgsel ved hjælp af IN
er i stand til at bruge en anti-semi join, hvilket betyder, at den ved, at dataene i t2 ikke er nødvendige, så så snart den finder et enkelt match, kan den stoppe med at scanne efter yderligere matches.
Hvis du begrænser din anden tabel til kun at have unikke værdier, vil du se den samme plan:
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;
Sammenfattende vil de to forespørgsler ikke altid give de samme resultater, og de vil ikke altid have den samme plan. Det afhænger virkelig af dine indekser og bredden af dine data/forespørgsler.