使用外部联接

仅当两个表中都至少有一个行符合联接条件时,内部联接才返回行。内部联接消除了与另一个表中的行不匹配的行。而外部联接会返回 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 ;