Hay al menos un caso en el que LEFT [OUTER] JOIN
es una mejor opción que [INNER] JOIN
. Hablo de obtener los mismos resultados usando OUTER
en lugar de INNER
.
Ejemplo (estoy usando base de datos AdventureWorks 2008 ):
-- Some metadata infos
SELECT fk.is_not_trusted, fk.name
FROM sys.foreign_keys fk
WHERE fk.parent_object_id=object_id('Sales.SalesOrderDetail');
GO
CREATE VIEW View1
AS
SELECT h.OrderDate, d.SalesOrderDetailID, o.ModifiedDate
FROM Sales.SalesOrderDetail d
INNER JOIN Sales.SalesOrderHeader h ON d.SalesOrderID = h.SalesOrderID
INNER JOIN Sales.SpecialOfferProduct o ON d.SpecialOfferID=o.SpecialOfferID AND d.ProductID=o.ProductID;
GO
CREATE VIEW View2
AS
SELECT h.OrderDate, d.SalesOrderDetailID, o.ModifiedDate
FROM Sales.SalesOrderDetail d
INNER JOIN Sales.SalesOrderHeader h ON d.SalesOrderID = h.SalesOrderID
LEFT JOIN Sales.SpecialOfferProduct o ON d.SpecialOfferID=o.SpecialOfferID AND d.ProductID=o.ProductID;
GO
SELECT SalesOrderDetailID
FROM View1;
SELECT SalesOrderDetailID
FROM View2;
Resultados de la primera consulta:
is_not_trusted name
-------------- ---------------------------------------------------------------
0 FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
0 FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID
Planes de ejecución para las dos últimas consultas:
Nota 1 / Vista 1: Si observamos el plan de ejecución para SELECT SalesOrderDetailID FROM View1
vemos un Eliminación de FK
porque el FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
la restricción es de confianza y tiene una sola columna. Pero, el servidor es forzado (debido a INNER JOIN Sales.SpecialOfferProduct
) para leer datos de la tercera tabla (SpecialOfferProduct) incluso el SELECT/WHERE
cláusulas no contiene ninguna columna de esta tabla y la restricción FK (FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID) es (también) de confianza. Esto sucede porque este último FK es de varias columnas.
Nota 2 / Vista 2: ¿Qué sucede si queremos eliminar la lectura (Scan
/Seek
) en Sales.SpecialOfferProduct
? Este segundo FK es de varias columnas y, en tales casos, SQL Server no puede eliminar el FK (consulte la publicación anterior del blog de Conor Cunnigham). En este caso, debemos reemplazar el INNER JOIN Sales.SpecialOfferProduct
con LEFT OUTER JOIN Sales.SpecialOfferProduct
para conseguir la eliminación de FK. Ambos SpecialOfferID
y ProductID
las columnas son NOT NULL
y tenemos un FK de confianza que hace referencia a SpecialOfferProduct
mesa.