联合查询是根据每个表之间的逻辑关系从两个或多个表中检索数据,而这逻辑关系则是每个表之间共同的列的关联性,这也是关系数据库查询的最主要的特征.
联合查询分为内连接,外连接和自连接查询. 外连接又可分为左外连接left outer join 、右外连接right outer join 、全外连接full outer join 查询.
联合查询效率较高,以下例子来说明联合查询(内联、左联、右联、全联)的好处:
表T1 |
UserId |
Name |
Password |
|
1 |
dong |
pdong |
|
2 |
hai |
phai |
表T2 |
UserId |
SID |
Grade |
|
1 |
1 |
2 |
|
3 |
2 |
3 |
如果想把用户信息、姓名、年级等都列出来,那么一般会这样写:select * from T1 ,T2 where T1.UserId = T2.UserId(其实这样的结果等同于select * from T1 inner join T2 on T1.UserId=T2.UserId )。
把两个表中都存在UserId 的行,将符合条件的行拿出来拼成一行(即内联),但后者的效率会比前者高很多,建议用后者(内联)的写法。
SQL语句:select * from T1 inner join T2 on T1.UserId=T2.UserId
运行结果 |
T1.UserId |
Name |
Password |
T2.UserId |
SID |
Grade |
|
1 |
dong |
pdong |
1 |
001 |
2 |
内连接将不符合连接条件的数据丢弃,只保留满足连接条件的行,连接表出现的顺序是无关紧要的,而在外连接中,连接双方有左右之分,如上边Sql语句"T1"为"左"表,"T2"为"右"表.根据左右表外连接分为左外连接,右外连接和全外连接.
显示左表T1中的所有行,并把右表T2中符合条件加到左表T1中;右表T2中不符合条件,就不用加入结果表中,并且NULL表示。
SQL语句:select * from T1 left outer join T2 on T1.UserId=T2.UserId
运行结果 |
T1.UserId |
Name |
Password |
T2.UserId |
SID |
Grade |
|
1 |
dong |
pdong |
1 |
001 |
2 |
|
2 |
hai |
phai |
NULL |
NULL |
NULL |
显示右表T2中的所有行,并把左表T1中符合条件加到右表T2中;左表T1中不符合条件,就不用加入结果表中,并且NULL表示。
SQL语句:select * from T1 right outer join T2 on T1.UserId=T2.UserId
运行结果 |
T1.UserId |
Name |
Password |
T2.UserId |
SID |
Grade |
|
1 |
dong |
pdong |
1 |
001 |
2 |
|
NULL |
NULL |
NULL |
3 |
002 |
3 |
显示左表T1、右表T2两边中的所有行,即把左联结果表+右联结果表组合在一起,然后过滤掉重复的。
SQL语句:select * from T1 full outer join T2 on T1.UserId=T2.UserId
运行结果 |
T1.UserId |
username |
password |
T2.UserId |
SID |
Grade |
|
1 |
dong |
pdong |
1 |
001 |
2 |
|
2 |
hai |
phai |
NULL |
NULL |
NULL |
|
NULL |
NULL |
NULL |
3 |
002 |
3 |
假设我们有三个表,A表,B表,C表.其数据量分别都为200条记录.并且假设每次都是遍历一半也就是100条的记录找到结果(一半情况下有较大的浮动,只是举例说明),并且假设每次查询都查出10个结果.
一般我们的查询语句是这样的:
select * from A,B,C where A.id=B.id and B.id=C.id
它相当于先将这三表进行组合,再遍历查询,查询量为100*100*100=100万.也就是从100万条数据中检索10条数据,听到一百万有什么感想,这仅是每个表中只有200条数据,如果每个表中有200万条数据呢?那会是一个多个大的负担(对于计算机).
那我们要如何来优化呢,上面其实已经说过了,那就是使用联合查询的前提条件,两个表的联合就没这问题,我们将三个表的联合查询拆分成两个两个的表的联合查询这样就大量减少了遍历的次数.
方式1: 将三表联合分成两个2表联合查询,如:先进行AB联合查询,再将结果与C联合. 这样查询遍历次数为:100*100+10*100 =1.1万.(只是检索10条数据)
SQL为:
select * from (select * from A , B where A.id = B.id) as ab, C where ab.id=C.id
方式2:先对各表进行过滤,再进行三表联合,或者2表联合: 这样查询的遍历次数为:100+100+100+10*10*10=1300.,或者:100+100+100+10*10+10*10=500.
SQL为:
select * from (select * from a where ...)as a,(select * from b where ....) as b, (select * from c where ....) as c where a.id=b.aid and b.id=c.bid
或者:
select * from (select * from (select * from a where ...)as a ,(select * from b where ....) as b where a.id = b.aid) as ab, (select * from c where ....) as c where ab.id=c.bid
这个时候或许数据就有比较的价值了,三个表联合查询和拆分开两个表联合遍历的数据条数100万,1.1万,0.13万,0.05万.我想着数字很值得我们深思考吧