目录
SQL FULL JOIN示例
高级示例
生产模式
注意NULL!
要点
SQL FULL JOIN将左外连接和右外连接的结果组合成一个结果。或者换句话说,它是一个内连接,包括来自左右表的不匹配行。
这是SQL FULL JOIN和inner join之间的主要区别。inner join返回与联接条件匹配的行,而FULL外部联接保证所有表行都包含在结果中。
我们在下面说明这一点:
正如预期的那样,它包括Mixer和Chopper的行。它们匹配两个表,包括Blender和Fred Or。这些是来自不匹配表的行。如果您查看我们关于LEFT和RIGHT连接的示例,您会看到其中包含一个或另一个,但不能同时包含两者。作为SQL FULL JOIN,两者都包括在内。
连接 FULL 通常称为 FULL OUTER JOIN。一般 形式为FULL JOIN :
SELECT table1.column1, table2.column2, …
FROM table1
FULL JOIN table2 ON table1.commonColumn = table2.commonColumn
注意:
- 在此示例中 , table2 是FULL 表,table1在左侧。
- 如果commonColumn值和table1.column1之间不匹配,则 返回NULL
- 如果commonColumn值和 table2.column2之间不匹配,则返回 NULL
完全外连接是左外连接和右外连接结果的组合。这种类型的连接返回的结果包括两个表中的所有行。在匹配发生的地方,值是相关的。从任一表匹配的地方都不匹配,然后返回NULL。
全外连接的基本语法是:
SELECT columnlist
FROM table
FULL OUTER JOIN othertable ON join condition
让我们看一下AdventureWork2012数据库的不同部分。这一次,我们将重点关注SalesOrderHeader和CurrencyRate表之间的关系。
模型如下图:
假设我们想知道我们可以下订单的所有货币以及以这些货币下的订单?
SELECT sales.SalesOrderHeader.AccountNumber,
sales.SalesOrderHeader.OrderDate,
sales.CurrencyRate.ToCurrencyCode,
sales.CurrencyRate.AverageRate
FROM sales.SalesOrderHeader
FULL OUTER JOIN
sales.CurrencyRate
ON sales.CurrencyRate.CurrencyRateID =
sales.SalesOrderHeader.CurrencyRateID
以下是结果的一部分,显示了一些销售与货币匹配的位置和一些不匹配的位置。存在不匹配的销售额的原因是这些销售额是以美元计价的。
在结果的下方,您会看到没有匹配销售额的货币。这反映了没有以这些货币进行销售的事实。
注意:看到美元上市令我感到惊讶,请参阅第42463行,因为我认为大部分销售额将以这种货币进行。我的想法是,对于所有美元交易,CurrencyRateID的SalesOrderHeader值设置为空,而不是尊重这些交易的汇率。我认为这是不一致的,这不是我的做法,但这不是我的数据库.....
高级示例到目前为止,我们已经了解了三种外部连接,但还没有探索一些更高级的概念,例如连接多个表和在我们的连接子句中使用多个条件。
我们在探索内部连接时涵盖了这些概念,所以我将向您展示的内容应该不会太新,但我认为回顾一下仍然有意义,因为在某些情况下,将完全连接与内部连接混合可能会产生意想不到的结果。
让我们将注意力转向生产模式并探索产品和类别。让我们生成一个包含所有产品类别和产品模型的列表。
生产模式Product与ProductModel和ProductSubcategory有一对多的关系。由于它位于这两个表之间,因此ProductModel和ProductSubcategory之间存在隐含的多对多关系。因此,它是外连接的良好候选者,因为可能存在没有分配产品的产品模型和没有产品的ProductSubcategory条目。
为了克服这种情况,我们将对ProductModel和ProductCategory表进行外连接。
这是SQL
SELECT PC.Name AS Category,
PSC.Name AS Subcategory,
PM.Name AS Model,
P.Name AS Product
FROM Production.Product AS P
FULL OUTER JOIN
Production.ProductModel AS PM
ON PM.ProductModelID = P.ProductModelID
FULL OUTER JOIN
Production.ProductSubcategory AS PSC
ON PSC.ProductSubcategoryID = P.ProductSubcategoryID
INNER JOIN
Production.ProductCategory AS PC
ON PC.ProductCategoryID = PSC.ProductCategoryID
ORDER BY PC.Name, PSC.Name
有几点需要注意:
- 我使用表别名使SQL更具可读性。
- 有不止一个完整的外部连接子句。
- ProductCategory表也是外连接的一部分
最初,当我为这个查询编写SQL时,我在ProductSubcategory和ProductCategory之间有一个内部连接,但我没有看到我期望的不匹配记录的NULL值。
将联接更改为完全外部联接后,我看到了预期的结果。发生这种情况的原因很微妙。
注意NULL!检查数据后,我确认所有类别都分配了子类别。鉴于此,您会认为内部联接会起作用;但是,考虑到执行整个语句并返回行时,每当产品未能匹配产品子类别时,该ProductSubcategoryID值为NULL。
根据定义,空值彼此不相等,因此内部连接失败。鉴于此,当这些值匹配ProductCategory时,它们不会包含在结果中,除非连接ProductCategory是外部连接。
事实上,连接不必是完全外连接,左连接也可以:
SELECT PC.Name AS Category,
PSC.Name AS Subcategory,
PM.Name AS Model,
P.Name AS Product
FROM Production.Product AS P
FULL OUTER JOIN
Production.ProductModel AS PM
ON PM.ProductModelID = P.ProductModelID
FULL OUTER JOIN
Production.ProductSubcategory AS PSC
ON PSC.ProductSubcategoryID = P.ProductSubcategoryID
LEFT OUTER JOIN
Production.ProductCategory AS PC
ON PC.ProductCategoryID = PSC.ProductCategoryID
ORDER BY PC.Name, PSC.Name
使用FULL JOINS时请记住,从一个表到另一个表的匹配可能会匹配多行。这意味着,您的结果可能在任一表中的结果中包含更多行。
当列不匹配时,请记住NULL被替换为值。
本文最初发布于SQL FULL Join - Essential SQL
https://www.codeproject.com/Articles/5326753/SQL-FULL-Join-Tutorial