[原创]多表连接(join)小结

参考:《sql查询初学者指南》第二版,机械工业出版社

基础

内链接就是对表A和表B以元组为单位做一个笛卡尔积,记为表C,然后在C中挑选出满足符合on 语句后边的限制条件的条目。

左连接就是在内连接的基础上,将A中有但C中没有的元组也加上。由于C的列数比A的列数多,所以这新增的元组左边照搬a,右边为null。

右链接就是在内连接的基础上,将B中有但C中没有的元组也加上。由于C的列数比B的列数多,所以这新增的元组右边照搬B,左边为null。

所谓的full join ,就是在join的结果d后边先加上left join 要加的项,再加上right join 要加的项

所谓的交叉连接(select * from tableName1 cross join tableName2)和select * from tableName1, tableName2是一样的,都是得到笛卡尔积。可以用select * from table1,table2 where....模拟join操作。

所谓的自身连接是指同一个表自己与自己进行连接。这种一元连接通常用于从自反关系(也称作递归关系)中抽取数据。例如人力资源数据库中雇员与老板的关系。

直接写join就是内连接,相当于inner join, inner可省

写left join或者right join就是外连接,outer可省

 

例子

有两表A和B

A

clip_image001

B

clip_image002

下面是一些select操作

select * from A cross join A

clip_image003

select * from A join B on A.name = B.name

就是对笛卡尔积,也即上边的cross join的结果进行进一步筛选,选出满足A.name=B.name的行。

只有两行符合条件

clip_image004

在上衣select语句的基础上增加了一行

select * from A left join B on A.name = B.name

clip_image005

同上

select * from A right join B on A.name = B.name

clip_image006

select * from A full join B on A.name = B.name

clip_image007

进阶

重要理论依据:

在可以指定一个表名的任何地方,都可以指定一个括号括起来的join子句。

在两个表的一个完整join语句出现的任何一个地方,我们都可以只用一个表名来代替它。

 

所谓“两个表的一个完整join语句”也即“join子句”,就是指如“A join B on A.a= B.b”这样一个完整的句子

比如:欲连接ABCDE五个表

可以这样:

Select * from A inner join(((

B inner join C on B.b = C.c)

inner join D on B.b = D.d)

inner join E on D.d = E.e)

on A.a = E.e

也可以这样:

select * from (((

A inner join B on A.a = B.b)

inner join C on C.c = A.a)

inner join D on D.d = C.c)

inner join E

on E.e = D.d

也可以这样:

select * from

A inner join B on A.a = B.b

inner join C on C.c = A.a

inner join D on D.d = C.c

inner join E on E.e = D.d

我们可以先把A和B连接起来,然后将结果与C连接,当然,如果C只和B相关而不和A相关的话,我们也可以先把B和C连接起来,结果再与A连接,只要保持关系是正确的,你可以以任意方式来定义嵌套的join。

然而大多数数据库系统会分析整个from子句,然后尝试确定组合连接表的最有效方式,也就是说数据库不不一定会从最里边的括号开始执行查询。这很可能打乱你的逻辑设计,得到意外的结果。

另外,一些数据库系统中的优化器对于join定义的顺序很敏感。如果你发现使用很多join的查询在一个较大的数据库上执行花很长时间,通过改变sql语句中的join顺序很可能能够使它运行的更快。

注意:有时候,你只需要A和C表中的一部分数据,但A和C只有通过B才能发生关系,那么你依然要先将A和B连接,然后再连接C

一个比较全面的例子:

select RCFiltered.ClassName, R.RecipeTitle

from

(select RecipeClassId,

RecipeClassDescription as ClassName

From Recipe_Classes as RC

where RC.ClassName = 'Salads' or RC.ClassName = 'Soup' or Rc.ClassName = 'Main Course')

as RCFiltered

left outer join Recipes as R

on RCFiltered.RecipeClassId = R.RecipeClassId

这个例子的内涵:

1. 在大多数sql的实现中,我们可以把from子句中的任何表名替换成一条完整的select语句.当然,必须分配一个相关名称。本例中为子select语句分配的名称为RCFiltered,在第7行。

2. 当我们决定以select代替表名的时候,要确保select的结果不仅包含想要出现在最终结果中的列,而且包含需要执行join的列。这就是为什么我们在嵌入的select语句中既看到了RecipeClassId又看到了RecipeClassDescription.

3. 我们给RecipeClassDescription一个别名ClassName,所以在第一行使用了RDFiltered的别名。第一行的select只看到了表RCFiltered,看不到表Recipe_Classes

posted on 2010-06-04 20:43  ybwang1989  阅读(35247)  评论(0编辑  收藏  举报

导航