Det finns minst ett fall där LEFT [OUTER] JOIN
är ett bättre alternativ än [INNER] JOIN
. Jag pratar om att få samma resultat med OUTER
istället för INNER
.
Exempel (jag använder AdventureWorks 2008-databas ):
-- 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;
Resultat för den första frågan:
is_not_trusted name
-------------- ---------------------------------------------------------------
0 FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
0 FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID
Utförandeplaner för de två senaste frågorna:
Anmärkning 1 / Visa 1: Om vi tittar på exekveringsplanen för SELECT SalesOrderDetailID FROM View1
vi ser en FK-eliminering
eftersom FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
begränsningen är pålitlig och den har en enda kolumn. Men servern är tvingad (på grund av INNER JOIN Sales.SpecialOfferProduct
) för att läsa data från den tredje tabellen (SpecialOfferProduct) även SELECT/WHERE
klausuler innehåller inga kolumner från den här tabellen och FK-begränsningen (FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID) är (också) betrodd. Detta händer eftersom denna sista FK är flerkolumn.
Anmärkning 2 / Visa 2: Vad händer om vi vill ta bort den lästa (Scan
/Seek
) på Sales.SpecialOfferProduct
? Denna andra FK är flerkolumn och för sådana fall kan SQL Server inte eliminera FK (se tidigare Conor Cunnigham blogginlägg). I det här fallet måste vi ersätta INNER JOIN Sales.SpecialOfferProduct
med LEFT OUTER JOIN Sales.SpecialOfferProduct
för att få FK eliminering. Båda SpecialOfferID
och ProductID
kolumner är NOT NULL
och vi har en pålitlig FK som refererar till SpecialOfferProduct
bord.