使用外部联接
仅当两个表中都至少有一个行符合联接条件时,内部联接才返回行。内部联接消除了与另一个表中的行不匹配的行。而外部联接会返回 FROM 子句中提到的至少一个表或视图中的所有行,只要这些行符合任何 WHERE 或 HAVING 搜索条件。将检索通过左外部联接引用的左表中的所有行,以及通过右外部联接引用的右表中的所有行。在完全外部联接中,将返回两个表的所有行。
SQL Server 对 FROM 子句中指定的外部联接使用下列 ISO 关键字:
LEFT OUTER JOIN 或 LEFT JOIN
RIGHT OUTER JOIN 或 RIGHT JOIN
FULL OUTER JOIN 或 FULL JOIN
使用左外部联接
考虑通过 ProductID 列联接 Product 表和 ProductReview 表。结果只显示已编写审核的产品。
若要在不论是否已编写审核的情况下包括所有产品,请使用 ISO 左外部联接。查询如下:
USE AdventureWorks;
GO
SELECT p.Name, pr.ProductReviewID
FROM Production.Product p
LEFT OUTER JOIN Production.ProductReview pr
ON p.ProductID = pr.ProductID
不管是否与 ProductReview 表的 ProductID 列相匹配,LEFT OUTER JOIN 都会在结果中包括 Product 表的所有行。请注意,对于结果中没有匹配的产品审核 ID 的产品,行的 ProductReviewID 列中则包含一个空值。
使用右外部联接
考虑通过 TerritoryID 列联接 SalesTerritory 表和 SalesPerson 表。结果显示已分配给销售人员的任何区域。ISO 右外部联接运算符 RIGHT OUTER JOIN 指明:不管第一个表中是否有匹配的数据,结果中都将包括第二个表中的所有行。
若要在不论是否为销售人员分配了区域的情况下在结果中包括所有销售人员,请使用 ISO 右外部联接。下面是 Transact-SQL 查询和右外部联接的结果:
USE AdventureWorks;
GO
SELECT st.Name AS Territory, sp.SalesPersonID
FROM Sales.SalesTerritory st
RIGHT OUTER JOIN Sales.SalesPerson sp
ON st.TerritoryID = sp.TerritoryID ;
下面是结果集。
Territory SalesPersonID
-------------------------------------------------- -------------
NULL 268
Northeast 275
Southwest 276
Central 277
Canada 278
Southeast 279
Northwest 280
Southwest 281
Canada 282
Northwest 283
NULL 284
United Kingdom 285
France 286
Northwest 287
NULL 288
Germany 289
Australia 290
(17 row(s) affected)
使用谓词可以进一步限定外部联接。此示例包含相同的右外部联接,但只包括销售额少于 $2,000,000 的销售区域:
USE AdventureWorks;
GO
SELECT st.Name AS Territory, sp.SalesPersonID
FROM Sales.SalesTerritory st
RIGHT OUTER JOIN Sales.SalesPerson sp
ON st.TerritoryID = sp.TerritoryID
WHERE st.SalesYTD < $2000000;
有关谓词的详细信息,请参阅 WHERE (Transact-SQL)。
使用完全外部联接
若要通过在联接的结果中包括不匹配的行来保留不匹配信息,请使用完全外部联接。SQL Server 提供了完全外部联接运算符 FULL OUTER JOIN,它将包括两个表中的所有行,不论另一个表中是否有匹配的值。
考虑通过 ProductID 列联接 Product 表和 SalesOrderDetail 表。结果只显示有销售订单的产品。ISO FULL OUTER JOIN 运算符指明:不管表中是否有匹配的数据,结果中都将包括两个表中的所有行。
您可以在完全外部联接中包括 WHERE 子句,仅返回两表之间没有匹配数据的行。以下查询只返回没有匹配销售订单的产品以及没有匹配产品的销售订单(虽然本例中所有销售订单都有匹配的产品)。
USE AdventureWorks;
GO
-- The OUTER keyword following the FULL keyword is optional.
SELECT p.Name, sod.SalesOrderID
FROM Production.Product p
FULL OUTER JOIN Sales.SalesOrderDetail sod
ON p.ProductID = sod.ProductID
WHERE p.ProductID IS NULL
OR sod.ProductID IS NULL
ORDER BY p.Name ;