ORACLE 多表连接与子查询

连接的类型

Oracle8i之前的表连接:

等值连接(Equijoin)

非等值连接(Non-Equijoin)

外连接(Outer join):-->左外连接-->右外连接

自连接(Self join)

Oracle9之后新引入的连接形式(支持SQL99规范)

交叉连接(Cross join)

自然连接(Natural join)

使用Using子句建立连接

使用on子句建立连接

外连接(Outer join):-->左外连接-->右外连接-->全外连接

 

oracle中的连接可分为,

1. 内连接(自然连接)

2. 外连接

1)左外连接 (左边的表不加限制)

2)右外连接(右边的表不加限制)

3)全外连接(左右两表都不加限制)

3. 自连接(同一张表内的连接)

4、交叉连接(cross join) (即 笛卡尔积)

5其他连接定义(可能属于上面3种中的某一种)

1)等值连接(equijoin

2)非等值连接(non-equijoin) 

3on建立查询连接

4using 建立查询连接

 

SQL的标准语法:

多表连接使用SQL99连接语法,两个以上的表进行连接时应依次/分别指定相临的两个表之间的连接条件.

select  字段列表   
from   table1   
[cross join table2] |   
[natural join table2] |   
[join table2 using(字段名)] |   
[join table2 on(table.column_name=table2.column_name)] |   
[(left | right | full out ) join table2   
on(table1.column_name=table2.column_name)]   
[cross join table3] |   
[natural join table3] |   
[join table3 using(字段名)] |   
[join table3 on(table.column_name=table3.column_name)] |   
[(left | right | full out ) join table3   
on(table2.column_name=table3.column_name)]...;  

inner join 表示内连接;

left join表示左外连接;

right join表示右外连接;

full join表示完全外连接;

on子句 用于指定连接条件。

in--------------等于列表中的任何一个

any--------------和子查询返回的任意一个值比较

all--------------和子查询返回的所有值比较

=--------------等于

>--------------大于

>=------------大于等于

<--------------小于

<=--------------小于等于

<>--------------不等于

 

注意:

如果使用from子句指定内、外连接,则必须要使用on子句指定连接条件;

如果使用(+)操作符指定外连接,则必须使用where子句指定连接条件; (+)在等号左边边指右连接,(+)在等号右边指左连接。

下面说明:内连接与自然连接基本相同,不同之处在于自然连接只能是同名属性的等值连接,而内连接可以使用using或on子句来指定连接条件

[1]外连接必须使用on或using子句提供相应的连接条件

[2]不能为using子句中所列举的列指定表别名,即使在group by和select子句中也是如此

[3]外连接规则:左连右补,右连左补,全连左右合并

 

1、内连接(Inner Join/Join

Inner join逻辑运算符返回满足第一个(顶端)输入与第二个(底端)输入联接的每一行。这个和用select查询多表(select …from tablename …where ….)是一样的效果,所以内连接用的很少。还有一点要说明的就是Join 默认就是inner join。 所以我们在写内连接的时候可以省略inner 这个关键字。where子句中指定连接条件当被连接的多个表中存在同名字段时,必须在该字段前加上"表名"作为前缀可以提高查询效率

select a.ename,b.dname from emp a,dept b where a.deptno  = b.deptno;

--

select a.ename,b.dname from emp a inner join dept b on a.deptno  = b.deptno;

--

select a.ename,b.dname from emp a join dept b on a.deptno  = b.deptno;

 

自然连接(Natural join) ------可理解为内连接的一种

自然连接是在两张表中寻找那些数据类型和列名都相同的字段,然后自动地将他们连接起来,并返回所有符合条件按的结果。例如下面效果是一样的:

select a.ename,b.dname from emp a  natural join dept b --自然连接

select a.ename,b.dname from emp a, dept b where a.deptno=b.deptno –非自然连接的普通where连接查询

 

2、外连接(Outer Join)

outer join则会返回每个满足第一个(顶端)输入与第二个(底端)输入的联接的行。它还返回任何在第二个输入中没有匹配行的第一个输入中的行。外连接分为三种: 左外连接,右外连接,全外连接。 对应SQLLEFT/RIGHT/FULL OUTER JOIN。 通常我们省略outer 这个关键字。 写成:LEFT/RIGHT/FULL JOIN

在左外连接和右外连接时都会以一张表为基表,该表的内容会全部显示,然后加上两张表匹配的内容。 如果基表的数据在另一张表没有记录。 那么在相关联的结果集行中列显示为空值(NULL)。

对于外连接, 也可以使用“(+) ”来表示。 关于使用(+)的一些注意事项:

1.+)操作符只能出现在where子句中,并且不能与outer join语法同时使用。(+)在等号左边边指右连接,(+)在等号右边指左连接。

2. 当使用(+)操作符执行外连接时,如果在where子句中包含有多个条件,则必须在所有条件中都包含(+)操作符

3.+)操作符只适用于列,而不能用在表达式上。

4.+)操作符不能与orin操作符一起使用。

5.+)操作符只能用于实现左外连接和右外连接,而不能用于实现完全外连接

 

2.1、左外连接(Left outer join/ left join

left join是以左表的记录为基础的,示例中Dave可以看成左表,BL可以看成右表,它的结果集是Dave表中的数据,在加上Dave表和BL表匹配的数据。换句话说,左表(Dave)的记录将会全部表示出来,而右表(BL)只会显示符合搜索条件的记录。BL表记录不足的地方均为NULL.

用(+)来实现, 这个+号可以这样来理解: 表示补充,即哪个表有加号,这个表就是匹配表。所以加号写在右表,左表就是全部显示,故是左连接。

查询出所有员工和其领导,最高领导没领导【左关联,则查询数据数目以左表为标准,使用left [outer] join… on (+)在右表字段的最后添加】

select a.ename "下属名称",b.ename "领导名称from emp a  left outer join emp b on a.mgr=b.empno --where b.empno is null

--

select b.ename "下属名称",a.ename "领导名称from emp a  right outer join emp b on b.mgr=a.empno

--

select a.ename "下属名称",b.ename "领导名称from emp a , emp b where  a.mgr=b.empno(+)

--

select b.ename "下属名称",a.ename "领导名称from emp a , emp b where  a.empno(+)=b.mgr

 

但是恰当使用子查询有利提高查询效率,如下:

select a.ename "下属名称",

(select b.ename from emp b where a.mgr=b.empno) "领导名称from emp a 

 

2.2、右外连接(right outer join/ right join

left join的结果刚好相反,是以右表(BL)为基础的显示BL表的所以记录,在加上DaveBL 匹配的结果。 Dave表不足的地方用NULL填充.

用(+)来实现, 这个+号可以这样来理解: 表示补充,即哪个表有加号,这个表就是匹配表。所以加号写在左表,右表就是全部显示,故是右连接。

--查询出所有不是领导的员工,最低员工下面没有员工【右关联,则查询数据数目以右表为标准,使用 right [outer] join on,或(+)在左表字段的最后添加】

select  a.ename "下属名称",b.ename "领导名称from emp a  right outer join emp b on a.mgr=b.empno where a.ename is  null

--

select  b.ename "下属名称",a.ename "领导名称from emp a  left outer join emp b on  a.empno=b.mgr where b.ename is  null

--

select  a.ename "下属名称",b.ename "领导名称from emp a , emp b where a.mgr(+)=b.empno and a.ename is  null

--

select  b.ename "下属名称",a.ename "领导名称from emp a  , emp b where  a.empno=b.mgr(+) and b.ename is  null

 

--或使用两个集合的差值,所有员工-领导员工,但是效率很低

select * from emp where empno in(

select a.empno from emp a

minus

select distinct b.mgr from emp b )

 

 

2.3、全外连接(full outer join/ full join

左表和右表都不做限制,所有的记录都显示,两表不足的地方用null 填充。 全外连接不支持(+)这种写法。

--使用全连接查询所有员工和对应的领导信息(全连接不足:领导和下属反回来时候,显示不准确)

select a.ename "领导",b.ename "下属from emp a  full outer join emp b on b.empno=a.mgr 

--或(union union all 性能差比较:union处理方式是先union all,然后过滤重复数据,所以union all性能较好)

select a.ename "领导",b.ename "下属from emp a  left outer join emp b on a.empno=b.mgr

union 

select b.ename "领导",a.ename "下属from emp a  left outer join emp b on b.empno=a.mgr;

--

select a.ename "领导",b.ename "下属from emp a  left outer join emp b on a.empno=b.mgr

union 

select a.ename "领导",b.ename "下属from emp a  right outer join emp b on a.empno=b.mgr;

 

3、自连接

自连接(self join)SQL语句中经常要用的连接方式,使用自连接可以将自身表的一个镜像当作另一个表来对待,从而能够得到一些特殊的数据。

--查询出所有员工和其领导,最高领导没领导(有一条数据没有被查询出来)

select a.ename "下属名称",b.ename "领导名称from emp a , emp b where a.mgr=b.empno

 

4、交叉连接(cross join) 

交叉连接不带WHERE 子句,它返回被连接的两个表所有数据行的笛卡尔积,返回到结果集合中的数据行数等于第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数。 

SQL语句如下: 

 

select * from emp where ename='FLJ1169';--查出一条结果数据

select * from dept;--查出4条结果数据

--交叉连接后,则多出3条交叉数据

 

select * from (select a.*,b.dname,b.deptno b_deptno from emp a cross join dept b ) where ename='FLJ1169'

 

5其他连接定义(可能属于上面3种中的某一种)

1)等值连接(equijoin

使用=符号连接

2)非等值连接(non-equijoin) 

多表中指使用除等号(=)外的其他运算符号作为连接查询。其他符号指:<><=>=<>between…and

3on建立查询连接

select a.empno,a.ename,a.sal,b.deptno,b.dname from emp a join dept b --on a.deptno=b.deptno

on (b.deptno=a.deptno);

4using 建立查询连接

select a.empno,a.ename,a.sal,b.dname from emp a  join dept b--on a.deptno=b.deptno  

using (deptno); 注意:但是查询结果列不能包含using条件的列,否则出错

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值