sql >> Base de Datos >  >> RDS >> Sqlserver

¿Dos selecciones o una selección + una unión en SQL?

Su idea de que deberían hacer el mismo trabajo no es cierta. Imagine este conjunto de datos de prueba:

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;

Resultados

ID
---
1
2
3

ID
---
1
1
1
2
2
3

Sus resultados solo son los mismos si la columna en la que está buscando es única.

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;

Aunque los resultados son los mismos, el plan de ejecución no lo es. La primera consulta usando IN es capaz de usar una combinación anti-semi, lo que significa que sabe que los datos en t2 no son necesarios, así que tan pronto como encuentre una única coincidencia, puede dejar de buscar más coincidencias.

Si restringe su segunda tabla para que solo tenga valores únicos, verá el mismo 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;

En resumen, las dos consultas no siempre arrojarán los mismos resultados y no siempre tendrán el mismo plan. Realmente depende de sus Índices y del ancho de sus datos/consulta.