Existuje alespoň jeden případ, kdy LEFT [OUTER] JOIN
je lepší možnost než [INNER] JOIN
. Mluvím o získání stejných výsledků pomocí OUTER
místo INNER
.
Příklad (používám databázi 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;
Výsledky pro první dotaz:
is_not_trusted name
-------------- ---------------------------------------------------------------
0 FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
0 FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID
Plány provedení pro poslední dva dotazy:
Poznámka 1 / Zobrazení 1: Pokud se podíváme na plán provádění pro SELECT SalesOrderDetailID FROM View1
vidíme Vyřazení FK
protože FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
omezení je důvěryhodné a má jeden sloupec. Server je však vynucený (kvůli INNER JOIN Sales.SpecialOfferProduct
) číst data ze třetí tabulky (SpecialOfferProduct), dokonce i SELECT/WHERE
klauzule neobsahuje žádné sloupce z této tabulky a omezení FK (FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID) je (také) důvěryhodné. To se děje, protože tento poslední FK je vícesloupcový.
Poznámka 2 / Zobrazení 2: Co když chceme odstranit přečtené (Scan
/Seek
) na Sales.SpecialOfferProduct
? Tento druhý FK je vícesloupcový a v takových případech nemůže SQL Server odstranit FK (viz předchozí příspěvek na blogu Conora Cunnighama). V tomto případě musíme nahradit INNER JOIN Sales.SpecialOfferProduct
s LEFT OUTER JOIN Sales.SpecialOfferProduct
za účelem vyřazení FK. Oba SpecialOfferID
a ProductID
sloupce jsou NOT NULL
a máme důvěryhodný FK odkazující na SpecialOfferProduct
tabulka.