LEFT [OUTER] JOIN
のケースが少なくとも 1 つあります。 [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
最後の 2 つのクエリの実行計画:
注 1 / ビュー 1: SELECT SalesOrderDetailID FROM View1
の実行計画を見ると、 FK の排除
FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
制約は信頼されており、単一の列があります。ただし、サーバーは強制されます (INNER JOIN Sales.SpecialOfferProduct
のため) ) SELECT/WHERE
でも 3 番目のテーブル (SpecialOfferProduct) からデータを読み取る 句にはこのテーブルの列が含まれておらず、FK 制約 (FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID) も (また) 信頼されています。これは、この最後の FK が複数列であるために発生します。
注 2 / ビュー 2: 読み取りを削除したい場合 (Scan
/Seek
) Sales.SpecialOfferProduct
で ?この 2 番目の FK は複数列であり、そのような場合、SQL Server は FK を削除できません (以前の Conor Cunnigham のブログ記事を参照してください)。この場合、INNER JOIN Sales.SpecialOfferProduct
を置き換える必要があります。 LEFT OUTER JOIN Sales.SpecialOfferProduct
を使用 FKの排除を得るために。両方 SpecialOfferID
および ProductID
列は NOT NULL
です SpecialOfferProduct
を参照する信頼できる FK があります。