sql >> Databasteknik >  >> RDS >> Sqlserver

Två markeringar eller en select + en join i SQL?

Din uppfattning att de borde göra samma arbete stämmer inte. Föreställ dig denna testuppsättning 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;

Resultat

ID
---
1
2
3

ID
---
1
1
1
2
2
3

Dina resultat är bara desamma om kolumnen du söker i är 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;

Även om resultaten är desamma, är utförandeplanen det inte. Den första frågan med IN kan använda en anti-semi-join, vilket betyder att den vet att data i t2 inte behövs, så så fort den hittar en enda matchning kan den sluta skanna efter ytterligare matchningar.

Om du begränsar din andra tabell till att bara ha unika värden, kommer du att se samma 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;

Sammanfattningsvis kommer de två frågorna inte alltid att ge samma resultat, och de kommer inte alltid att ha samma plan. Det beror verkligen på dina index och bredden på din data/fråga.



  1. Dynamisk rullgardinslista för olika länder, stater, geografiska platser?

  2. hur man arbetar med rekursiv fråga i MySql?

  3. hur man infogar värden med kommatecken?i switch-satsen

  4. Det gick inte att ladda typen 'NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle'