Има поне един случай, при който LEFT [OUTER] JOIN
е по-добра опция от [INNER] JOIN
. Говоря за получаване на същите резултати с помощта на OUTER
вместо INNER
.
Пример (използвам база данни 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;
Резултати за първото запитване:
is_not_trusted name
-------------- ---------------------------------------------------------------
0 FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
0 FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID
Планове за изпълнение за последните две заявки:
Бележка 1 / Изглед 1: Ако разгледаме плана за изпълнение за SELECT SalesOrderDetailID FROM View1
виждаме FK елиминиране
защото FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
ограничението е надеждно и има една колона. Но сървърът е принуден (поради INNER JOIN Sales.SpecialOfferProduct
), за да прочетете данни от третата таблица (SpecialOfferProduct) дори SELECT/WHERE
клаузи не съдържа никакви колони от тази таблица и ограничението FK (FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID) е (също) надеждно. Това се случва, защото последният FK е многоколонен.
Бележка 2 / Изглед 2: Ами ако искаме да премахнем прочетеното (Scan
/Seek
) на Sales.SpecialOfferProduct
? Този втори FK е многоколонен и за такива случаи SQL Server не може да елиминира FK (вижте предишната публикация в блога на Conor Cunnigham). В този случай трябва да заменим INNER JOIN Sales.SpecialOfferProduct
с LEFT OUTER JOIN Sales.SpecialOfferProduct
за да получите FK елиминиране. И двете SpecialOfferID
и ProductID
колоните са NOT NULL
и имаме доверен FK, посочващ SpecialOfferProduct
таблица.