Il y a au moins un cas où LEFT [OUTER] JOIN
est une meilleure option que [INNER] JOIN
. Je parle d'obtenir les mêmes résultats en utilisant OUTER
au lieu de INNER
.
Exemple (j'utilise base de données 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;
Résultats pour la première requête :
is_not_trusted name
-------------- ---------------------------------------------------------------
0 FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
0 FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID
Plans d'exécution pour les deux dernières requêtes :
Remarque 1/Vue 1 : Si nous regardons le plan d'exécution pour SELECT SalesOrderDetailID FROM View1
nous voyons un Élimination FK
car le FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
La contrainte est approuvée et elle a une seule colonne. Mais, le serveur est forcé (à cause de INNER JOIN Sales.SpecialOfferProduct
) pour lire les données de la troisième table (SpecialOfferProduct) même le SELECT/WHERE
clauses ne contient aucune colonne de cette table et la contrainte FK (FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID) est (également) approuvée. Cela se produit parce que ce dernier FK est multicolonne.
Remarque 2/Vue 2 : Et si nous voulons supprimer la lecture (Scan
/Seek
) sur le Sales.SpecialOfferProduct
? Ce deuxième FK est multicolonne et dans de tels cas, SQL Server ne peut pas éliminer le FK (voir le billet de blog précédent de Conor Cunnigham). Dans ce cas, nous devons remplacer le INNER JOIN Sales.SpecialOfferProduct
avec LEFT OUTER JOIN Sales.SpecialOfferProduct
afin d'obtenir l'élimination FK. Les deux SpecialOfferID
et ProductID
les colonnes sont NOT NULL
et nous avons un FK de confiance faisant référence à SpecialOfferProduct
tableau.