C'è almeno un caso in cui LEFT [OUTER] JOIN
è un'opzione migliore di [INNER] JOIN
. Parlo di ottenere gli stessi risultati usando OUTER
invece di INNER
.
Esempio (sto usando database 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;
Risultati per la prima query:
is_not_trusted name
-------------- ---------------------------------------------------------------
0 FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
0 FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID
Piani di esecuzione per le ultime due query:
Nota 1 / Vista 1: Se esaminiamo il piano di esecuzione per SELECT SalesOrderDetailID FROM View1
vediamo un Eliminazione FK
perché FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
vincolo è attendibile e ha una singola colonna. Ma il server è forzato (a causa di INNER JOIN Sales.SpecialOfferProduct
) per leggere i dati della terza tabella (SpecialOfferProduct) anche il SELECT/WHERE
clausole non contiene colonne di questa tabella e il vincolo FK (FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID) è (anche) attendibile. Questo accade perché quest'ultimo FK è multicolonna.
Nota 2 / Vista 2: E se volessimo rimuovere la lettura (Scan
/Seek
) sul Sales.SpecialOfferProduct
? Questo secondo FK è multicolonna e per tali casi SQL Server non può eliminare l'FK (vedi precedente post sul blog di Conor Cunnigham). In questo caso dobbiamo sostituire INNER JOIN Sales.SpecialOfferProduct
con LEFT OUTER JOIN Sales.SpecialOfferProduct
per ottenere l'eliminazione dall'FK. Entrambi SpecialOfferID
e ProductID
le colonne sono NOT NULL
e abbiamo un FK affidabile che fa riferimento a SpecialOfferProduct
tabella.