Der er mindst ét tilfælde, hvor LEFT [OUTER] JOIN
er en bedre mulighed end [INNER] JOIN
. Jeg taler om at få de samme resultater ved at bruge OUTER
i stedet for INNER
.
Eksempel (jeg bruger AdventureWorks 2008-database ):
-- 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;
Resultater for den første forespørgsel:
is_not_trusted name
-------------- ---------------------------------------------------------------
0 FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
0 FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID
Udførelsesplaner for de sidste to forespørgsler:
Bemærkning 1 / Visning 1: Hvis vi ser på eksekveringsplanen for SELECT SalesOrderDetailID FROM View1
vi ser en FK-eliminering
fordi FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
begrænsning er tillid til, og den har en enkelt kolonne. Men serveren er tvunget (på grund af INNER JOIN Sales.SpecialOfferProduct
) for at læse data fra den tredje tabel (SpecialOfferProduct) selv SELECT/WHERE
klausuler indeholder ingen kolonner fra denne tabel, og FK-begrænsningen (FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID) er (også) tillid til. Dette sker, fordi denne sidste FK er multikolonne.
Bemærkning 2 / Visning 2: Hvad hvis vi vil fjerne læst (Scan
/Seek
) på Sales.SpecialOfferProduct
? Denne anden FK er multikolonne, og i sådanne tilfælde kan SQL Server ikke eliminere FK'en (se tidligere Conor Cunnigham blogindlæg). I dette tilfælde skal vi erstatte INNER JOIN Sales.SpecialOfferProduct
med LEFT OUTER JOIN Sales.SpecialOfferProduct
for at få FK-eliminering. Begge SpecialOfferID
og ProductID
kolonner er NOT NULL
og vi har en betroet FK, der henviser til SpecialOfferProduct
tabel.