Há pelo menos um caso em que
LEFT [OUTER] JOIN
é uma opção melhor que [INNER] JOIN
. Eu falo sobre obter os mesmos resultados usando OUTER
em vez de INNER
. Exemplo (estou usando o banco de dados 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 da primeira consulta:
is_not_trusted name
-------------- ---------------------------------------------------------------
0 FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
0 FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID
Planos de execução para as duas últimas consultas:
Observação 1/Visualização 1: Se olharmos para o plano de execução para
SELECT SalesOrderDetailID FROM View1
vemos um Eliminação FK
porque o FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
restrição é confiável e tem uma única coluna. Mas, o servidor é forçado (por causa de INNER JOIN Sales.SpecialOfferProduct
) para ler dados da terceira tabela (SpecialOfferProduct) até mesmo o SELECT/WHERE
cláusulas não contém nenhuma coluna desta tabela e a restrição FK (FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID) é (também) confiável. Isso acontece porque este último FK é multicoluna. Observação 2 / Visualização 2: E se quisermos remover a leitura (
Scan
/Seek
) no Sales.SpecialOfferProduct
? Este segundo FK é multicoluna e, para esses casos, o SQL Server não pode eliminar o FK (consulte a postagem anterior no blog de Conor Cunnigham). Nesse caso, precisamos substituir o INNER JOIN Sales.SpecialOfferProduct
com LEFT OUTER JOIN Sales.SpecialOfferProduct
para obter a eliminação FK. Ambos SpecialOfferID
e ProductID
colunas são NOT NULL
e temos um FK confiável referenciando SpecialOfferProduct
tabela.