数据库中多表连接的原理实现

数据库中多表连接的原理实现,第1张

多变关联的实现方式有hash join,merge join,nested loop join 方式,具体使用那种内型的连接,主要依据:

1.当前的优化器模式(all_rows和rule)

2.取决于表的大小

3.取决于关联字段是否有索性

4.取决于关联字段是否排序

Hash  join散列连接,优化器选择较小的表(数据量少的表)利用连接键(join key)在内存中建立散列表,将数据存储到hash列表中,然后扫描较大的表

select A.*,B.* from A left join B on a.id=b.id。

先是从A表读取一条记录,用on条件匹配B表的记录,行成n行(包括重复行)如果B表没有与匹配的数据,则select中B表的字段显示为空,接着读取A表的下一条记录,right join类似。

left join基本是A表全部扫描,在表关键中不建议使用子查询作为副表,比如select A.*,B.*from A left join (select * from b where b.type=1 )这样A表是全表扫描,B表也是全表扫描。若果查询慢,可以考虑关联的字段都建索引,将不必要的排序去掉,排序会导致运行慢很多。

主副表条件过滤:

table a(id, type):

id    type

----------------------------------

1      1       

2      1         

3      2   

表b结构和数据

table b(id, class):

id    class

---------------------------------

1      1

2      2

Sql语句1: select a.*, b.* from a left join b on a.id = b.id and a.type = 1

执行结果为:

a.id    a.type    b.id    b.class

----------------------------------------

1        1            1        1

2        1            2        2

3        2

a.type=1没有起作用

sql语句2:

select a.*, b.* from a left join b on a.id = b.id where a.type = 1

执行结果为:

a.id    a.type    b.id    b.class

----------------------------------------

1        1            1        1

2        1            2        2

sql语句3:

select a.*, b.* from a left join b on a.id = b.id and b.class = 1

执行结果为:

a.id    a.type    b.id    b.class

----------------------------------------

1        1            1        1

2        1           

3        2

b.class=1条件过滤成功。

结论:left join中,左表(主表)的过滤条件在on后不起作用,需要在where中添加。右表(副表)的过滤条件在on后面起作用。

Mysql join原理:

Mysql join采用了Nested Loop join的算法,

###坐车 回去补充。

其实不能说连接查询有什么优缺点

要非得说的话也许是

当需要即时计算聚集值并把该值用于外部查询中进行比较时,子查询就比连接更具有优势。

如果查询中的SELECT列表所包含的列来自于多个表,那么这时连接的优势要胜过子查询

以下是连接查询

你慢慢看吧

一.自连接查询:

一个表自己与自己建立连接称为自连接或自身连接。

进行自连接就如同两个分开的表一样,可以把一个表的某一行与同一表中的另一行连接起来。

例:

查询选学“101”课程的成绩高于“9505201”号学生成绩的所有学生记录,

并按成绩从高到低排列。

select x.* from sclass x,sclass y

where x.cno=''101'' and x.degree>y.degree and y.sno=''9505201'' and y.cno=''101''

order by x.degree desc

二. 内连接查询

内连接(INNER JOIN)使用比较运算符进行表间某(些)列数据的比较 *** 作,并列出这些表中与连接条件相匹配的数据行。根据所使用的比较方式不同,内连接又分为等值连接、自然连接和不等连接三种。

1、等值连接:

所谓等值连接,是指表之间通过“等于”关系连接起来,产生一个临时表,

然后对该临时表进行处理后生成最终结果。其查询结果中列出被连接表中的所有列,

包括其中的重复列。

SELECT *

FROM authors AS a INNER JOIN publishers AS p

ON a.city=p.city

我们可以有两种方式,这两种是等效的

一种是:SELECT e.employeeid,e.employeename,d.deptname FROM EmployeeTB AS e,DeptTB AS d WHERE e.deptid=d.deptid

另外一个是:SELECT e.employeeid,e.employeename,d.deptname FROM EmployeeTB AS e INNER JOIN DeptTB AS d ON e.deptid=d.deptid

3、自然连接:

在等值连接中消除重复列就是自然连接。(state,city在两个表中都存在)

SELECT a.*,p.pub_id,p.pub_name,p.country

FROM authors AS a INNER JOIN publishers AS p

ON a.city=p.city

三 外连接查询 (左外连接、右外连接、全外连接)

左向外联接的结果集包括 LEFT OUTER 子句中指定的左表的所有行,而不仅仅是联接列所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值

右向外联接是左向外联接的反向联接。将返回右表的所有行。如果右表的某行在左表中没有匹配行,则将为左表返回空值。

A left join B 的连接的记录数与A表的记录数同

A right join B 的连接的记录数与B表的记录数同 这种说法是错误的,只有当表A与表B是一对一时才成立。

首先我们做两张表:员工信息表和部门信息表,在此,表的建立只为讲述连接的概念,所以字段非常的简单

EmployeeTB(员工信息表):

employeeid employeename deptid

0001 张三 01

0002 李四 01

0003 王五 02

0004 赵六 02

0005 郑七 NULL

DeptTB(部门信息表)

deptid deptname

01 技术部

02 市场部

03 工程部

1左外联结

但是有些情况下,我们需要知道所有员工的信息,即使他不属于任何部门。这样我们就可以采用外连接,在这里为左外连接,也就是连接中的左表的表中的记录,无论能不能在右表中找到匹配的项,都要检索,如果没有匹配的项目,那么右表中的字段值为NULL(空),在这里就代表,此员工不属于任何部门。

检索语句为:

SELECT e.employeeid,e.employeename,d.deptname FROM EmployeeTB AS e LEFT OUTER JOIN DeptTB AS d ON e.deptid=d.deptid

检索的结果都是:

employeeid employeename deptname

0001 张三 技术部

0002 李四 技术部

0003 王五 市场部

0004 赵六 市场部

0005 郑七 NULL

但是在这里,工程部同样不会被检索,因为,deptname是在连接的右边的表中,“工程部”在左表中不存在任何的记录,所以不会被检索。这里关注的是“连接中的左边的表”

2、右外连接

有时,我们需要知道,全部部门的信息,即使它没有任何的员工。在我们的查询中部门表在连接的右边,如果我们想知道右边表中的所有记录信息,那么就可以采用右外连接,如果此记录在左边的表中找不到匹配项,则相应字段(employeeid,employeename)为NULL

检索语句为:

SELECT e.employeeid,e.employeename,d.deptname FROM EmployeeTB AS e RIGHT OUTER JOIN DeptTB AS d ON e.deptid=d.deptid

检索的结果都是:

employeeid employeename deptname

0001 张三 技术部

0002 李四 技术部

0003 王五 市场部

0004 赵六 市场部

NULL NULL 工程部

但在这里,郑七是不会被检索了,因为它在右表中找不到匹配项,这里关注的是“连接中的右边的表”

3、完全外连接

如果我们想知道所有的记录呢?无论员工有没有部门,部门有没有员工,我们都需要检索。这里就可以使用完全外连接。关注连接中的两部分。如果没有部门,部门为空,没有员工,员工信息为空。

检索语句为:

SELECT e.employeeid,e.employeename,d.deptname FROM EmployeeTB AS e FULL OUTER JOIN DeptTB AS d ON e.deptid=d.deptid

检索的结果都是:

employeeid employeename deptname

0001 张三 技术部

0002 李四 技术部

0003 王五 市场部

0004 赵六 市场部

0005 郑七 NULL

NULL NULL 工程部

四.交叉连接

交叉连接不带WHERE 子句,它返回被连接的两个表所有数据行的笛卡尔积,返回到结果集合中的数

据行数等于第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数。

例,titles表中有6类图书,而publishers表中有8家出版社,则下列交叉连接检索到的记录数将等

于6*8=48行。

三个表的左连接示例:

准备数据:

表t1

字段名:t1_id,username,psw

表t2

字段名:t2_id,gname,t1_id //这里一个t1_id对应多个t2_id

t3

字段名:t3_id,realname,tel,t1_id //这里一个t1_id对应一个t3_id

多表联结指的是由两个表以上的join运算,有两种形式。

一种是多个表对应相同的外键;另一个多表间对应各不相同的外键。

如果两个以上的表与外一个表联结时对应相同的键值,则两表的关系是1:1关系,如果是自然的联接,则可以直接则两个表相联后同联结其子表,这样的速度较快些,但没有必要将两者每两者的联结果关系都写清楚。

多表间对应不同的外键时,按外键关系写就可以了!


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/10020157.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-04
下一篇 2023-05-04

发表评论

登录后才能评论

评论列表(0条)

保存