在oracle的SQL语句经常使用的链接有内链接(inner join),外链接(outer join)等,内链接又包括等值链接,非等值链接,自链接;而外链接又分为左链接和右链接全链接。其中默认的是内链接的等值链接。sql
为了方便咱们建立两张最简易的表A、B,具体的表结构参看下面,来分析内链接与外链接的区别oracle
图1 图2测试
两个表要作链接,必需要有链接字段,而在表A和表B中链接字段是Aid和Bnamid,下图说明了链接之间关系图3spa
图3code
(1) 内链接:利用内链接(等值)就可获取蓝色的公共部分C,即图3中的数据集C,结果集为以下:innodb
图4table
其实select * from A join B on A.Aid=B.Bnamid;等价于select * from A,B where A.Aid=B.Bnamid;
注:非等值链接主要的话是针对一个范围来查询数据,自链接主要就是把1张表当作两张表来用
(2)外链接:分为左外链接(left join)与右外链接(right join)
左外链接即公共显示的蓝色部分C1+显示黄色的记录集A1,显示语句等价于class
select * from A,B where A.Aid=B.Bnamid(+); 效率
注:sql中(+),表示外链接 能够省略 left/right join 。。and。。等关键字,其中(+)在等号左边表示右外链接,在等号右边表示左外链接。select
图 5
右外链接即公共显示的蓝色部分C1+显示绿色的B1,显示语句等价于
select * from A,B where A.Aid(+)=B.Bnamid;
图6
表A和表B状况是相对的,以上实验都是A在左边的状况,其实A left join B与B right join A的状况的结果集是同样的。
另外,全链接 full join表示三个部分所有包含到结果集,彼此没有与之匹配的数据行填充null。
测试表环境:
drop table if exists join_a; create table join_a( f1 int not null comment '字段1', f2 int not null comment '字段2' )engine=innodb default charset=utf8 comment '链接测试A表'; insert into join_a(f1,f2) value(1,1); insert into join_a(f1,f2) value(1,1); insert into join_a(f1,f2) value(1,2); insert into join_a(f1,f2) value(1,2); insert into join_a(f1,f2) value(2,3); insert into join_a(f1,f2) value(2,3); insert into join_a(f1,f2) value(2,4); insert into join_a(f1,f2) value(2,4); drop table if exists join_b; create table join_b( f1 int not null comment '字段1', f2 int not null comment '字段2' )engine=innodb default charset=utf8 comment '链接测试B表'; insert into join_b(f1,f2) value(1,5); insert into join_b(f1,f2) value(1,5); insert into join_b(f1,f2) value(1,6); insert into join_b(f1,f2) value(1,6); insert into join_b(f1,f2) value(2,7); insert into join_b(f1,f2) value(2,7); insert into join_b(f1,f2) value(2,8); insert into join_b(f1,f2) value(2,8);
select t1.* ,t2.* from join_a t1 left join join_b t2 on t1.f1=t2.f1;
运行结果:
+----+----+----+----+ | f1 | f2 | f1 | f2 | +----+----+----+----+ | 1 | 1 | 1 | 5 | | 1 | 1 | 1 | 5 | | 1 | 2 | 1 | 5 | | 1 | 2 | 1 | 5 | | 1 | 1 | 1 | 5 | | 1 | 1 | 1 | 5 | | 1 | 2 | 1 | 5 | | 1 | 2 | 1 | 5 | | 1 | 1 | 1 | 6 | | 1 | 1 | 1 | 6 | | 1 | 2 | 1 | 6 | | 1 | 2 | 1 | 6 | | 1 | 1 | 1 | 6 | | 1 | 1 | 1 | 6 | | 1 | 2 | 1 | 6 | | 1 | 2 | 1 | 6 | | 2 | 3 | 2 | 7 | | 2 | 3 | 2 | 7 | | 2 | 4 | 2 | 7 | | 2 | 4 | 2 | 7 | | 2 | 3 | 2 | 7 | | 2 | 3 | 2 | 7 | | 2 | 4 | 2 | 7 | | 2 | 4 | 2 | 7 | | 2 | 3 | 2 | 8 | | 2 | 3 | 2 | 8 | | 2 | 4 | 2 | 8 | | 2 | 4 | 2 | 8 | | 2 | 3 | 2 | 8 | | 2 | 3 | 2 | 8 | | 2 | 4 | 2 | 8 | | 2 | 4 | 2 | 8 | +----+----+----+----+ 32 rows in set
说明:取t1表的第一行,扫瞄t2表,按条件作对比,若是知足条件,就加入返回结果表.
而后取t1表的第二行,扫瞄t2表,按条件作对比,若是知足条件,就加入返回结果表.
。。。。。。。。。。。。。
重复以上过程,直到t1表扫描结束。
select t1.* ,t2.* from join_a t1 left join join_b t2 on t1.f1=t2.f1 and t1.f2=1;
说明:给左表加条件的时候,左表知足条件的,按上面的过程返回值,左表不知足条件的,直接输出,右表的列补null。
如下三种语句查询结果同样:
--左外链接(where条件),不完整的数据不显示 select t1.* ,t2.* from join_a t1 left join join_b t2 on t1.f1=t2.f1 where t1.f2=1; --内链接(on+and条件),不完整的数据不显示 select t1.* ,t2.* from join_a t1 inner join join_b t2 on t1.f1=t2.f1 and t1.f2=1; --使用where条件来链接表(and条件),不完整的数据不显示 select t1.* ,t2.* from join_a t1 , join_b t2 where t1.f1=t2.f1 and t1.f2=1; --其中后两种效率更高
说明:若是有where子语句,先执行where后链接查询,执行where的时候已经把不知足条件的直接去除,因此最后的结果没有填充null的行。效果同inner join。
当外链接使用where条件语句的时候,能够把left join(或者right join) 改成inner jin, 由于inner join比left join 要快!
select t1.* ,t2.* from join_a t1 left join join_b t2 on t1.f1=t2.f1 and t2.f2=5;
如下三种语句查询结果同样:
--on+where,不完整的数据不显示 select t1.* ,t2.* from join_a t1 left join join_b t2 on t1.f1=t2.f1 where t2.f2=5; --inner+on+and,不完整的数据不显示 select t1.* ,t2.* from join_a t1 inner join join_b t2 on t1.f1=t2.f1 and t2.f2=5; --where+and,不完整的数据不显示 select t1.* ,t2.* from join_a t1 , join_b t2 where t1.f1=t2.f1 and t2.f2=5; --其中后两种效率更高