当前位置: 代码迷 >> SQL >> SQL应用与开发:(5)多个数据表的连接
  详细解决方案

SQL应用与开发:(5)多个数据表的连接

热度:96   发布时间:2016-05-05 10:39:19.0
SQL应用与开发:(五)多个数据表的连接

数据库中的各个表中存储着不同的数据,用户往往需要用多个表中的数据来组合、提炼出所需要的信息。如果一个查询需要对多个表进行操作,就称为连接查询。连接查询的结果集或结果表称为表之间的连接。查询实际上是通过各个表之间共同列的关联性来查询数据的,它是关系型数据库查询最主要的特征。

实现连接的结果是在向数据库增添新类型的数据方面没有限制,具有很大的灵活性。通常总是通过连接创建一个新表,以包含不同表中的数据。如果新表有合适的域,就可以将它连接到现有的表。


1.简单连接操作

最简单的连接方式是在SELECT语句的FROM子句中用逗号将不同的基表隔开,使用WHERE子句创建的同等连接是使第一个基表中一个或者多个列中的值与第二个基表中相应的一个或者多个列的值相等的连接。这样在查询结果中只显示两个基表中列的值相匹配的行。但是值得注意的是,无论不同表中的列是否具有相同的列名,都相应的通过增加表名来限制列名。

例如,在数据库“销售关系系统”中,从“业务员信息”和“客户信息”连个表中,查询“业务员编号”大于1004,并且在SELECT列表中增加一个列“业务员编号”:

SELECT 业务员信息.业务员编号,业务员信息.业务员编号,客户信息.客户姓名,客户信息.客户地址,客户信息.联系电话

FROM 业务员信息,客户信息

WHERE 业务员信息.业务员编号=客户信息.所属业务员编号 AND 业务员信息.业务员编号>1004

执行后,便是我们条件的结果。

在该查询中,我们也可以使用相关名称,“业务员信息”表用别名A代替,“客户信息”表用B代替,当引用这连个表时,除了FROM子句外,在SELECT语句的任何地方都可以使用A和B,那么我们上述的语句就变成了:

SELECT A.业务员编号,A.业务员编号,B.客户姓名,B.客户地址,B.联系电话

FROM 业务员信息 A ,客户信息 B

WHERE A.业务员编号=B.所属业务员编号 AND A.业务员编号>1004

其执行结果,和前面的完全相同。

这也为后面的多个表的连接的 学习奠定了基础。例如,在数据库“珠宝销售系统”中,基于“珠宝信息”、“珠宝商信息”和“销售明细信息”三个表创建一个查询。要求返回“珠宝信息”表中的列“珠宝名称”,“珠宝商信息”表中的列“珠宝商姓名”和“销售明细信息”表中的列“利润”:

SELECT A.珠宝名称,B.珠宝商姓名,C.利润

FROM 珠宝商信息 AS A ,珠宝商信息 AS B,销售明细信息 AS C

WHERE A.珠宝代号=C.珠宝代号 AND A.珠宝商编号=B.珠宝商编号

执行后,便是所查询结果集。


2.内连接

内连接是最常用的连接查询,一般用INNER JION关键字来指定内连接。但是,INNER不是必需的。如果只用JOIN关键字,还必须定义一个ON子句。内连接查询操作列出与连接条件匹配的数据行,它使用比较运算符比较被连接的列值。


2.1等值连接

所谓等值连接解释在连接条件中使用等于号(=)运算符比较被连接列的值,其查询结果中列出被连接表中的所有列,包括其中的重复列。换句话说,基表之间的连接通过相等的列值连接起来的查询就是等值连接查询。

等值连接查询可以用两种表示方式来指定连接条件。例如,在数据库“销售关联系统”中,基于“商品信息”和“供应商信息”两个表创建一个查询。限定查询条件为两个表中的“供应商编号”相等时返回,并要求返回的列为“商品信息”表中的“商品名称”和“供应商信息”表中的列“供应商名称”、“联系人姓名”。

SELECT A.商品名称,B.供应商名称,B.联系人姓名,A.单价

FROM 商品信息 A,供应商名称 B

WHERE A.供应商编号=B.供应商编号

在上述语句的WHERE子句中,用"="指定查询为等值连接查询。

还可以在查询语句的FROM子句中使用INNER JOIN关键字连指定查询是等值连接查询。

SELECT A.商品名称,B.供应商名称,B.联系人姓名,A.单价

FROM 商品信息 A INNER JOIN 供应商信息 B

                           ON A.供应商编号=B.供应商编号 

执行后,与上述语句所得结果相同。

也可以对连接查询所得的结果利用ORDER BY子句进行排序。例如,将上述的的等值连接查询的查询按列“单价”的降序进行排列。

SELECT A.商品名称,B.供应商名称,B.联系人姓名,A.单价

FROM 商品信息 A INNER JOIN 供应商信息 B

                           ON A.供应商编号=B.供应商编号 

ORDER BY A.单价 DESC

运行后,唯一与上述结果不同的是,该查询的结果根据“单价”对查询的结果进行了降序排序。


2.2非等值连接

在等值连接查询的连接条件中不适用等号,而使用其他比较符就构成了非等值连接查询。也就是说,非等值连接查询是在连接条件中使用了等于运算符以外的其他比较运算符比较被连接列的列值。在非等值连接查询中,可以使用的比较傲运算符有:>、<、>=、<=、!=,还可以使用BETWEEN...AND之类的关键字。

例如,从数据库“销售管理系统”中,基于“供应商信息”和“入库单信息”两个表创建一个查询。限定查询条件为两个表中的“供应商编号”不相等,并返回列“供应商名称”和“供应商所在城市”。

SELECT 供应商名称,供应商所在城市

FROM 供应商信息 A INNER JOIN 入库单信息 B

ON A.供应商编号!=B.供应商编号

执行上述语句后,其查询结果返回80行,单大部分都是重复的。我们利用下述语句来消除重复行。

SELECT  DISTINCT 供应商名称,供应商所在城市

FROM 供应商信息 A INNER JOIN 入库单信息 B

ON A.供应商编号!=B.供应商编号

该查询结果中信息与“供应商信息”表中列“供应商名称”和“供应商所在城市”中的信息完全相同,所以上述查询并没有实际应用价值,这就说明非等值连接查询往往需要同其他连接查询结合使用,尤其是与等值连接查询结合。

2.3自然连接

自然连接是在连接条件中使用等于号(=)运算符比较被连接列的列值,但它使用选择列表指出查询结果集中所包含的列,并删除连接表中的重复列。简单的说,在等值连接中去掉重复的属性列,即为自然连接。

自然连接为具有相同名称的列自动进行记录匹配。自然连接不必指定任何同等连接条件。SQL实现方式判断出具有相同名称的列然后形成匹配。然而,自然连接虽然可以指定查询结果包括的列,但是不能指定被匹配的列。

例如,在数据库“珠宝营销系统”中,基于“顾客信息”和“珠宝商信息”两个表创建了一个自然连接查询。这个连接查询的限定条件是两个表中“消费者所在城市”和“珠宝商所在城市”相同,并按照列“消费者姓名”、“消费者地址”、“珠宝商姓名”和“珠宝商地址”返回查询结果。

SELECT 消费者姓名,消费者地址,消费者所在城市 AS 城市,珠宝商姓名。珠宝商地址

FROM 顾客信息 A INNER JOIN B

ON A.消费者所在城市=B.珠宝商所在城市

执行上述语句后,对其结果进行分析。尽管利用自然查询能够消除查询结果中重复的行,但是从上述语句的查询结果中能够发现,该查询结果也是由笛卡尔积形成的。


3.外连接

当至少有一个同属于两个表的行符合连接条件时,内连接才返回行。而外连接返回所有的匹配航和一定的不匹配行,这主要取决于所建立的连接的类型。SQL支持的3种类型的外连接:

左外连接:返回所有的匹配行并从关键字JOIN左边的表中返回所有不匹配的行。

右外连接:返回所有的匹配行并从关键字JOIN右边的表中返回所有不匹配的行。

完全连接:返回所有的匹配行和不匹配的行。


3.1左外连接

左外连接的查询结果集中包括指定左表中的所有行,而不仅仅是连接列所匹配的行。如果左表的某行在右表中没有找到相匹配的行,则结果集中的右表的相对应位置为NULL。

在左外连接查询的SELECT语句中,用LEFT OUTER JOIN关键字对两个基表进行连接。

例如,在数据库“珠宝营销系统”中,以在同一个城市的消费者和珠宝商为条件,对“消费者信息”和“珠宝商信息”表进行左外连接查询。

SELECT  消费者姓名,消费者地址,消费者所在城市 AS 城市,珠宝商姓名,珠宝商地址

FROM 顾客信息 A LEFT OUTER JOIN 珠宝商信息 B

ON A.消费者所在城市=B.珠宝商所在城市

执行后,查询其结果中包含了三行含有NULL值得数据,尽管这三行没有匹配列,但在查询结果中仍然被包括进去,原因就是这三行中列“消费者姓名”中的信息包含在左表中。这就是说,在进行左外连接查询时,无论左表中的行是否能够在右表中找到匹配的行,查询结果中都将被显示在该行,与其他行唯一不同的是,右表中与该行对应的位置用NULL值代替。


3.2右外连接

右外连接就是左外连接的反向连接,只不过在插叙结果集中包括的是指定右表的所有行。如果右表的某行在左表中没有找到相匹配的行,则结果集中的左表的相对应位置为NULL。

在右外连接查询的SELECET语句中,用RIGHT OUTER JOIN关键字对两个基表进行连接。

例如,在数据库“珠宝商营销系统”中,以在同一个城市的消费者和珠宝商为条件,对“消费者信息”和“珠宝商信息”表进行右外连接。

SELECT  消费者姓名,消费者地址,消费者所在城市 AS 城市,珠宝商姓名,珠宝商地址

FROM 顾客信息 A RIGHT OUTER JOIN 珠宝商信息 B

ON A.消费者所在城市=B.珠宝商所在城市

执行后,查询其结果中包含了两行含有NULL值得数据,尽管这两行没有匹配列,但在查询结果中仍然被包括进去,原因就是这两行中列“珠宝商姓名”中的信息包含在右表中。这就是说,在进行右外连接查询时,无论右表中的行是否能够在左表中找到匹配的行,查询结果中都将被显示在该行,与其他行唯一不同的是,左表中与该行对应的位置用NULL值代替。


3.3完全连

完全连接返回左表和右表中的所有行。当某行在另一个表中没有匹配行时,则另一个表与之相对应列值为NULL。如果表之间右匹配行,则整个结果集包含基表的数据值。

在完全连接查询的SELECT语句中,用FULL OUTER JOIN关键字对两个基表进行连接。

例如,在数据库“珠宝商营销系统”中,以在同一个城市的消费者和珠宝商为条件,对“消费者信息”和“珠宝商信息”表进行完全连接。

SELECT  消费者姓名,消费者地址,消费者所在城市 AS 城市,珠宝商姓名,珠宝商地址

FROM 顾客信息 A FULL OUTER JOIN 珠宝商信息 B

ON A.消费者所在城市=B.珠宝商所在城市

执行后,查询其结果中包含了六行含有NULL值得数据,尽管这六行没有匹配列,但在查询结果中仍然被包括进去,原因就是这两行中列“珠宝商姓名”中的信息包含在右表中。这就是说,在进行完全连接查询时,无论左表中还是右表是否能够找到匹配的行,它都在查询结果中显示该行,而只是在找不到匹配的位置上用NULL值代替。


4.联合查询

如果有多个不同的查询结果,但又不希望将它们连接在一起,组成数据。在这种情况下,可以使用UNION子句。使用UNION子句的查询称为联合查询,它可以将两个或者更多查询的结果组合为一个单个结果集,该结果集包含联合查询中所有查询结果集中的全部行数据。联合查询不同于对两个表中的列进行连接查询,前者是组合两个表中的行,后者是匹配两个表中的列数据。联合查询的语法格式为:

SELECT <select_list>

FROM <table_reference>

[WHERE <search_condition>]

{UNION [ALL]

SELECT <select_list>

FROM <table_reference>

[WHERE <search_condition>]}

[ORDER BY <order_condition>]

在进行联合查询时,UNION子句会自动删除重复的行,查询结果的列标题为第一个查询语句的列标题。因此,必须在第一个查询语句中定义列标题。

例如,从数据库”珠宝营销系统“的"顾客信息"表中,查询”消费者所在城市“为”北京市“的消费者的姓名、家庭住址和联系电话,并为其增加类型列为”类别“,列的内容为”消费者“;从”珠宝商信息“表中,查询”珠宝商所在城市“同样是”北京市“的珠宝商的相关信息,并增加一个列,列的内容为“珠宝商”;最后,将两个查询的结果联合在一起。

SELECT 消费者姓名 AS 姓名,消费者地址 AS 家庭住址,联系电话,'消费者' AS 类别

FROM 顾客信息

WHERE 消费者所在城市='北京市'

UNION

SELECT 珠宝商姓名,珠宝商地址,电话,'珠宝商'

FROM 珠宝商信息

WHERE 珠宝商所在城市='北京市'

在使用UNION的SELECT语句中,如果要对联合查询结果进行排序,则必须使用第一个查询语句中的列名、列标题或者列序号。并且排序子句ORDER BY中最好用数字来指定排序次序,如果不用数字,则联合查询的子查询中的列名就需要相同,也可以使用别名来统一列名。

另外,在对联合查询的结果进行排序的结果进行排序时,必须把ORDER BY子句放在SELECT子句的后面。

例如,从数据库“销售管理系统”的“客户信息”表中,查询“客户编号”不大于1005的客户的姓名、家庭住址和联系电话,并为其增加类型列“职能”,列的内容为“客户”;从“业务员信息”表中,查询“业务员编号”不大于1005的业务员的姓名、家庭住址和联系电话,并增加一个列,列的内容为“业务员”;最后,将两个查询结果联合在一起,并按类型“职能”的升序排列。

SELECT 客户姓名 AS 姓名,客户地址 AS 家庭住址,联系电话,'客户' AS 职能

FROM 客户信息

WHERE 客户编号<= 1005

UNION

SELECT 业务员姓名,家庭住址,电话,'业务员'

FROM 业务员信息

WHERE 业务员编号<=1005

ORDER BY 职能

UNION ALL是另外一种对表进行联合的方法。它与UNION唯一不同的区别是它不删除重复的行,也不对行进行自动排序。在对表进行联合查询时,如果以希望在查询结果中显示重复的行,就可以使用UNION ALL。在此,不再一一举例。


5.交叉连接和自连接

在连接查询中还有两个比较特殊的连接查询方式:交叉连接和自连接。在交叉连接的查询结果中,两个表中每两个可能成对的行占一行。自连接就是一个表与自身进行连接查询。


5.1交叉连接

两个表进行交叉连接将生成来自这两个表的各行的所有可能组合。交叉连接在不带WHERE子句时,返回的是被连接的两个表所有行的笛卡尔积,即返回到结果集中的行数等于第一个表中符合查询条件的行数乘以第二个表中符合查询条件的行数。当交叉连接带有WHERE子句时,返回的是连接两个表的所有行的笛卡尔积减去WHERE子句所现在而省略的所有行数。

交叉连接与前面介绍的基本连接操作非常相似。唯一不同的是,在FROM子句中,多个表名之间不是用逗号,而是用CROSS JOIN关键字隔开;并且在进行交叉连接时,不能像内连接和外连接一样使用ON 关键字来限定连接条件,但是可以将连接条件限定在WHERE子句中。

例如,在数据库“销售管理系统”中,对“商品信息”表和“供应商信息”表进行交叉连接。要求返回商品的产地和供应商所在城市都是“上海市”或者构思“南京市”的相关信息。

SELECT 商品信息.商品名称,商品信息.产地,供应商信息.供应商名称

FROM 商品信息 CROSS JOIN 供应商信息

WHERE 商品信息.产地=供应商信息.供应商所在城市

AND (商品信息.产地='上海市' OR 商品信息.产地='南京市')

ORDER BY 商品信息.产地


5.2自连接

连接不仅可以再不同表之间进行,也可以使一个表同其自身进行连接,这种连接成为自连接,相应的查询称为子连接查询。子连接是与表本身进行的内连接或者外连接。

子连接的连接操作可以利用别名的方法实现一个表自身的连接。实质上,这种子身连接方法与两个表的连接操作完全相似。只是在每次列出这个表时便为它命名一个别名。

例如,对数据库“销售管理系统”中的“客户信息”表进行自连接,查询“客户地址”相同的客户信息,并在查询结果中只返回“客户地址”为“北京市海淀区”或者“北京市朝阳区”的相关信息。

SELECT A.客户姓名,A.联系电话,A.客户地址,B.客户姓名,B.联系电话

FROM 客户信息 A INNER JOIN 客户信息 B

ON A.客户地址=B.客户地址

WHERE A.客户地址='北京市海淀区'

OR A.客户地址='北京市朝阳区'

由于此查询涉及“客户信息”表与自身的连接,因此“客户信息”表以两种角色显示。要区分这连个角色,必须在FROM子句中为“客户信息”表中提供两个不同的别名(A 和B),这两个别名用来限定查询中的列名。如果希望消除客户与自身相匹配的行,则只需在上述语句中添加一个限定条件,即将上述语句改为:

SELECT A.客户姓名,A.联系电话,A.客户地址,B.客户姓名,B.联系电话

FROM 客户信息 A INNER JOIN 客户信息 B

ON A.客户地址=B.客户地址

WHERE (A.客户地址='北京市海淀区'

OR A.客户地址='北京市朝阳区')

AND A.客户姓名<>B.客户姓名

该查询结果和上述查询结果相比较,发现在该查询结果中消除了客户与其自身相匹配的行。


6.学习小结

在学习本章节的内容时,很是感到头疼,这内容也的确是多了点儿。但是,其联系却是十分的紧密,学起来不是很费力,总算把学的知识总结起来了。

在对于多个数据表的连接学习中,数据表的联系很是实际化,在不断练习中学到更多的知识。


  相关解决方案