第4章 连接
4.2内部连接
当返回列的名称在连接结果中多次出现时,必须完全限定列的名称。可以通过以下两种方法中的任一种来确定列名。
1.提供选择列所在表的表名,接着是一个点号(.)和列名(即表.列名)
2.为表提供一个别名,接着是一个点号(.)和列名(即别名.列名)
例子:

SELECT Person.BusinessEntity.*,HumanResources.Employee.BusinessEntityID
 FROM Person.BusinessEntity
 INNER JOIN HumanResources.Employee
 ON Person.BusinessEntity.BusinessEntityID
    =HumanResources.Employee.BusinessEntityID

取别名的方法比较麻烦一点,但这能够降低代码的冗余性并提高查询语句的可读性。

SELECT pbe.*,hre.BusinessEntityID
 FROM Person.BusinessEntity pbe
 INNER JOIN HumanResources.Employee hre
 ON pbe.BusinessEntityID=hre.BusinessEntityID


建议在语句中要么全部使用别名,要么从不使用别名。如果决定给表取别名,则必须在查询的每一个部分都是用别名。

INNER JOIN(内部连接)--类似WHERE子句
内部连接是一个排他的连接-即排除在两表中没有匹配的所有记录(第一个指定的表(即左表)和第二个指定的表(即右表))。

SELECT CAST(LastName+','FirstName AS varchar(35)) AS Name,AccountNumber
 FROM Person.Person pp
 JOIN Sales.Cutomer sc
 ON pp.BusinessEntityID=sc.BusinessEntityID

4.3外部连接

SELECT sso.SpecialOfferID,Description,DiscountPct,ProductID
 FROM Sales.SpecialOffer sso
 LEFT OUTER JOIN Sales.SpecialOfferProduct ssop
 ON sso.SpecialOfferID=ssop.SpecialOfferID
 WHERE sso.SpecialOfferID!=1


本例使用了LEFT JOIN,而SpecialOffer表在JOIN关键字的左侧。如果使用连接,但在SpecialOfferProduct表中没有与之匹配的记录,则如何处理?如果在右侧表中不存在与左侧表匹配的字段时,SQL Server会为其他任意值填充NULL值。

1.找出孤立或不匹配的记录

SELECT Description
 FROM Sales.SpecialOfferProduct ssop
 RIGHT OUTER JOIN Sales.SpecialOffer sso
 ON ssop.SpecialOfferID=sso.SpecialOfferID
 WHERE sso.SpecialOfferID!=1
 AND ssop.SpecialOfferID IS NULL

4.3.2处理更复杂的外部连接
应首先使用内部连接,然后尽量少地使用外部连接,这样可减少代码中的错误。

4.4完全连接
完全连接(FULL JOIN或称为FULL OUTER JOIN)用来将JOIN两侧的数据全部匹配,并返回所有的记录,不论记录在JOIN的哪一侧的表中。完全连接的目的是返回数据之间的所有关系,不需给定连接两侧表的优先顺序,返回所有记录,而不丢弃任何记录。
如果会使用LEFT JOIN和RIGHT JOIN,则FULL JOIN返回的结果最容易理解。根据完全连接的JOIN字段,返回所有匹配的记录。还可以返回所有左侧表中的任何记录,而在右侧表中没有匹配的记录时右侧列返回NULL值。还可以返回右侧列中的记录,而在左侧表中没有匹配的记录时左侧列返回NULL值。

4.5交叉连接
交叉连接不使用ON运算符,而将JOIN左侧的所有记录与另一侧的所有记录连接。

SELECT v.VendorName,a.Address
 FROM Vendors v
 CROSS JOIN Address a


在Vendors表中有3个记录,而在Address表中有5个记录。则使用交叉连接可以返回15个记录。

4.7联合
UNION用于使两个或两个以上的查询产生一个结果集。联合不是真正的连接,作用更像将一个查询返回的数据附加到另一个查询结果的末尾。JOIN将信息水平连接(添加更多列),而UNION将数据垂直连接(添加更多行)。
当使用UNION处理查询时,要注意几个关键点:
1.所有UNION的查询必须在SELECT列表中有相同的列数。即如果在SELECT列表中第一个查询选择了3列,则第二个查询也要选择3列。如果第一个查询选择5列,则第二个查询也要选择5列。不管第一个查询选择多少列,随后的查询必须选择相同的列。
2.UNION返回的结果集的标题仅从第一个查询获得。若第一个查询的SELECT列表为SELECT Coll,Col2 AS Second,Col3 FROM...,则不管随后的查询列如何命名或取别名,使用UNION返回的列的标题分别为Coll、Second和Col3。
3.查询中的对应列的数据类型必须隐式一致。注意这里没有要求相同的数据类型,只要数据类型可隐式转换。
4.与其他非UNION查询不同,UNION查询的默认返回选项为DISTINCT,而不是ALL.

SELECT col2
 FROM UnionTest1
 UNION
 SELECT col4
 FROM UnionTest2

4.8本章小结
1.要排除不匹配的字段,使用内部连接。
2.要检索尽可能匹配的数据,但又要包含JOIN一侧的表的所有数据时使用外部连接。
3.要检索尽可能匹配的数据,但又要包含JOIN两侧的表的所有数据时使用完全连接。
4.要基于两个表的记录建立笛卡尔积时使用交叉连接。交叉连接通常用于科学领域和生成测试数据。
5.要将第二个查询结果附加到第一个查询结果时使用联合。