Oracle数据库数据编程SQL<1.4 表连接、子查询>

目录

一、表连接

(一)内连接 inner join,等值连接

(二)外连接 outer join,等值连接

1、左外连接 left{outer} join

2、右外连接 right{outer} join

3、全外连接 full{outer} join

(三)不等值连接

(四)自连接

(五)用where的方式进行表连接

1、显示两张表共有的部分,没有(+)加号是内连接(inner join)

2、显示左表全部的信息,(+)加号在等号右边是左连接(left join)

3、显示右表全部的信息,(+)加号在等号左边是右连接(right join)

(六)总结

1. on 和 where 的区别

2. 内连接 inner join,显示双方共有的部分

3. 等值连接 =

4. 不等值连接 <>、<、>、=、!=

5. 自连接

6. 外链接

二、子查询

(一)单行单列

(二)多行单列、多列

三、子查询的分类

(一)非相关子查询(标准子查询)(嵌套子查询)

(二)相关子查询

(三)exists的用法

(四)in的特殊用法

(五)with as 用法

1、要点:

四、总结

五、可以学习的练习

六、练习


sql的分类:
DQL(Data Query Language):数据查询语言

DDL(Data Definition Language):数据定义语言

DML(Data Manipulation Language):数据操纵语言

DCL(Data Control Language):数据控制语言

DTL(Data Transaction Language):数据事务语言 

TCL(Transaction Control Language):事务控制语言

一、表连接

(一)内连接 inner join,等值连接

只显示两张表共有的数据 (满足关联条件的数据显示,不满足关联条件的数据不显示)

--语法
select 列 from 表1
inner join 表2
on 表1.关联列=表2.关联列

--练习
select*from emp
inner join dept
on emp.deptno=dept.deptno

select *from emp a
inner join salgrade b
on a.sal between b.losal and b.hisal

(二)外连接 outer join,等值连接

1、左外连接 left{outer} join

显示左表的全部数据和右表满足关联条件的数据

select 列
from 表1--左表
left join 表2 --右表
on 表1.关联列=表2.关联列

2、右外连接 right{outer} join

显示右表的全部数据和左表满足关联条件的数据

select 列
from 表1--左表
right join 表2 --右表
on 表1.关联列=表2.关联列

3、全外连接 full{outer} join

显示两张表共有和独有的数据

select 列
from 表1
full join 表2
on 表1.关联列=表2.关联列

select *
from emp
full join dept
on emp.deptno=dept.deptno

练习:

--1. hr的employees和departments连接到一起显示
  select *
  from employees e
  inner join departments d
  on d.department_id=e.department_id

--2. 把deparments的全部数据显示在左边,employees的数据显示在右边
  select *
  from departments d
  left join employees e
  on e.department_id=d.department_id

--3. 显示employees的全部数据和departments符合关联条件的数据
  select *
  from employees e
  inner join departments d
  on e.department_id=d.department_id

--4. 显示departments的全部数据和employees符合关联条件的数据
  select *
  from departments d
  inner join employees e
  on e.department_id=d.department_id

--5. 显示两张表共有的和独有的数据
  select *
  from departments d
  full join employees e
  on e.department_id=d.department_id

(三)不等值连接

--语法
select 列
from 表1
inner join 表2
on > < >=

--举例
select sal,b.*
from emp a
inner join salgrade b
on a.sal between b.losal and b.hisal

(四)自连接

--查询员工编号、姓名及其经理编号、经理姓名
select a.empno ,a.ename,a.mgr,b.empno,b.ename
from emp a
inner join emp b
on a.mgr=b.empno

(五)用where的方式进行表连接

--where的方法不能显示两表全部数据(不能全外连接)

1、显示两张表共有的部分,没有(+)加号是内连接(inner join)

select*
from emp a,dept b
where a.deptno=b.deptno

2、显示左表全部的信息,(+)加号在等号右边是左连接(left join)

select*
from emp a,dept b
where a.deptno=b.deptno(+)

3、显示右表全部的信息,(+)加号在等号左边是右连接(right join)

select*
from emp a,dept b
where a.deptno(+)=b.deptno

/*笛卡尔积:

使用where进行多表连接但是没有加关联条件时出现

数据量较大时会造成数据库很慢

一般应避免出现笛卡尔积

*/

--emp dept连接后显示部门是10或30或者40部门的员工姓名部门编号、部门所在地,按照部门编号排序
select a. ename,b.deptno,b.loc
from emp a,dept b
where a.deptno(+)=b.deptno and b.deptno in(10,30,40)
order by b.deptno

select a. ename,b.deptno,b.loc
from emp a
right join dept b
on a.deptno=b.deptno
where b.deptno in (10,30,40)
order by b.deptno

--查询各个部门的名称和员工人数
select dname,count(ename)
from emp e,dept d
where e.deptno(+)=d.deptno
group by dname

select dname,count(ename)
from dept b
left join emp e
on b.deptno=e.deptno
group by dname

(六)总结

1. on 和 where 的区别

on 是对连接前的数据进行限制。即连接的前提条件

where 是对连接后的数据进行限制

2. 内连接 inner join,显示双方共有的部分

3. 等值连接 =

4. 不等值连接 <>、<、>、=、!=

5. 自连接

同一张表自己连接,可以是inner join、outer join、等值、不等值

6. 外链接

(1)左连接--左表数据全部显示,右表满足条件的显示不满足条件的显示为空

(2)右连接--右表数据全部显示,左表满足条件的显示不满足条件的显示为空

(3)全外连接--显示双方两表共有的和独有的数据

tip:工作中一般用左连接(left join / where =(+))

=========================================================================

=========================================================================

二、子查询

什么是子查询?在结果集里继续查询,即——在一个sql语句里再嵌套多个sql。

子查询先于主查询独立执行,返回的结果供主查询使用。

命令 执行顺序 子查询可以用在的地方
with as 1 一定要接子查询★
select 8 可以,但是不建议(标量子查询)
from 2 可以,子查询当临时表用★(内联视图)
inner join 3 可以,子查询当临时表用
on 4 可以接单行单列,一般不用
where 5 可以,经常用★
group by 6 不可以
having 7 可以
order by 9 可以,必须是单行单列

(一)单行单列

返回的结果是一个值,可以放在可以放一个值得地方。

(二)多行单列、多列

可以把子查询当集合使用,可以使用多行比较运算符 in、any、all、exists

·【all】和【any】 必须和单行比较运算符结合使用

·【>all】 大于最大的

·【>any】 大于最小的

·【=all】 空

·【=any】 相当于 【in

三、子查询的分类

(一)非相关子查询(标准子查询)(嵌套子查询)

先运行子查询,再运行主查询

--查询emp表工资大于30部门所有人的员工工资
select * from emp where sal

--多列:经常当做临时表使用
--查询emp表中20部门的员工中工资大于2000的员工姓名 、工作
select ename ,job,sal
from (select *from emp where deptno=20)
where sal>2000

--查询(emp表中和‘SCOTT’的 工作一样的)员工姓名,工作,经理编号
select ename,job,mgr
from emp
where job=(select job from emp where ename='SCOTT')

--查询emp表中和员工编号是7788的员工部门相同的员工编号、姓名、部门编号
select empno,ename,deptno
from emp
where deptno =(select deptno from emp where empno='7788')

--查询1981年入职的员工中,经理是KING的员工信息
select * from emp
where mgr=(select empno from emp where ename='KING')and to_char(hiredate,'yyyy')=1981

--查询部门所在地是NEW YORK 的员工信息(用表连接和子查询两种办法)
select * from EMP
where DEPTNO =(select DEPTNO from DEPT where loc='NEW YORK' )

SELECT * 
FROM DEPT D
INNER JOIN EMP E ON D.DEPTNO =E.DEPTNO
WHERE D.LOC='NEW YORK'

(二)相关子查询

先运行主查询,再运行子查询,子查询提前运行不能得到明确的结果

·子查询在主查询的结果的基础上进行查询

·子查询和主查询在执行过程中互相依赖

select empno,ename,(select dname from dept b where a.deptno=b.deptno)
from emp a

改写:
select empno,ename,dname
from emp a
inner join dept b
on a.deptno=b.deptno
select empno,ename,dname
from emp a ,dept b
where a.deptno=b.deptno

(三)exists的用法

判断是否存在,如果子查询返回>=1列(有返回值),那么执行上面的sql

如果子查询返回空,那么结果为空。

select * from emp
where exists(select 123 from dual)--非相关子查询

--关心的是子查询是否有返回值

select * 
from emp a
where exists(select 1 from dept b where a.deptno=b.deptno and loc='NEW YORK')

select a.* 
from emp a
inner join dept b
on a.deptno=b.deptno and loc='NEW YORK'

--not in 向 not exists 改写时,要注意去空值。

--查询经理不是KING也不是SCOTT的员工信息
select * 
from emp a
inner join emp b
on a.mgr=b.empno
where b.ename not in('KING','SCOTT')

---------------------------------------------------------
select * from emp a
where not exists(select 1 from emp b where a.mgr=b.empno
and b.ename in ('KING','SCOTT'))
and mgr is not null

---------------------------------------------------------
select * from emp a
where mgr not in
(select empno from emp where ename in ('KING','SCOTT'))

(四)in的特殊用法

--查询emp表中和经理编号是7788的员工的工作和部门编号相同的员工信息

select job,deptno
from emp
where mgr=7788

单列多行子查询

select *
from emp
where job in(select job from empwhere mgr=7788)
and deptno in(select deptno from emp where mgr =7788)

in的特殊用法如下

select *
from emp
where(job,deptno) in (select job,deptno from emp where mgr=7788)

--查询emp表中和经理是KING的员工的工作、部门编号相同的员工信息
select *
from emp
where (job,deptno,ename)
in(select job,deptno,ename from emp
where mgr=(select empno from emp where ename='KING'))

(五)with as 用法

1、要点:

(1)看懂别人的

(2)尝试让自己会写,锻炼自己的改写能力

(4)在sql优化上,性能更好

(5)可以简化多次查询的SQL,增强可读性和提高性能,多次复用

(6)要和select语句一起执行

(7)whih as 可以给多个子查询起别名,用逗号连接,最后一个不加逗号

(8)with as -----必须和下面的select语句一起执行

with a as(select ename,deptno,sal,job from emp),
     b as(select deptno,dname from dept)
select dname,sum(sal)
from a,b
where a.deptno=b.deptno
group by dname
order by sum(sal) desc

-----------------------------------------------------------------------
-----------------------------------------------------------------------
--查询每个部门工资最高的
--员工编号,姓名,职位,工资,部门编号,部门名称
--结果按照部门编号排序
with a as (select deptno,max(sal) maxsal from emp group by deptno)
select empno,ename,job,sal,e.deptno,dname
from emp e
inner join dept d
on e.deptno=d.deptno
inner join a
on e.deptno=a.deptno
where a.deptno=e.deptno and a.maxsal=e.sal
-----------------------------------------------------------------------
with a as (select deptno,max(sal) maxsal from emp group by deptno)
select empno,ename,job,sal,e.deptno,dname
from emp e,dept d,a
where e.deptno=d.deptno and a.maxsal=e.sal and a.deptno=e.deptno
-----------------------------------------------------------------------
select empno,ename,job,sal,deptno
from emp
where(deptno,sal) in (select deptno,max(sal) from emp group by deptno)

四、总结

--=======================================================================
--=======================
子查询:必须有关联条件
--=======================
1、非相关子查询
  (1)单行单列--相当于一个值
  (2)多行单列--可以作为一个结果集,要用多行比较运算符in、any、all、exists
  (3)多列 --多用作临时表
2、相关子查询
  (1)标量子查询--需要改写。即:select后的子查询需要改写
  (2)exists 后的相关子查询可以和in/表连接互相改写
--=======================================================================

--=======================================================================
--=======================
with as:必须和select执行
--=======================
(1)可以简化SQL,增强可读性和提高性能
(2)多次复用
(3)要和select语句一起执行
(4)可以给多个子查询起别名,用逗号连接,最后一个不加逗号

with t1 as(select colum1,colum2,colum3 from table1),
     t2 as(select colum1,colum2,colum3 from table2),
     t3 as(select colum1,colum2,colum3 from table3)
select t1.*,t2.*.t3.*
from t1
left join t2 on t1.colum1 = t2.colum1
left join t3 on t1.colum1 = t3.colum1
--=======================================================================

五、可以学习的练习

--查询emp表每个部门的人数,平均工资,总工资
--最高工资,最低工资
--显示(最高工资减去最低工资)除以人数 最大的部门
select (g.d-g.e)/max(g.a)
from (select deptno,count(ename) a,avg(sal) b,sum(sal)c,max(sal) d,min(sal) e
      from emp
      group by deptno) g
group by (g.d-g.e)
-----------------------------------------------------------------------------------
select g.deptno
from (select deptno,
             count(ename) a,
             avg(sal) b,
             sum(sal)c,
             max(sal) d,
             min(sal) e
       from emp
       group by deptno
      ) g
where (g.d-g.e)/g.a =(select max((t.d-t.e)/t.a) 
                      from (select deptno,
                                   count(ename) a,
                                   avg(sal) b,
                                   sum(sal)c,
                                   max(sal) d,
                                   min(sal) e
                             from emp
                             group by deptno
                            ) t
                      )----这里不可以直接引用
-----------------------------------------------------------------------------------
--改写成with as
with g as (select deptno,count(ename) a,avg(sal) b,sum(sal)c,max(sal) d,min(sal) e
           from emp
           group by deptno)-----------反复用的的表就可以考虑用with as
select g.deptno
from g
where (g.d-g.e)/g.a=(select max((g.d-g.e)/g.a) from g)---这里就可以直接引用
-----可以学习的点在于,能否直接引用

六、练习

--1、查询emp表中和'SCOTT'工作一样的员工姓名、工作、经理编号
select*
from(select ename,job,mgr from emp )
where job=(select job from emp where ename='SCOTT')
----------------
select ename,job,deptno
from emp
where job=(select job from emp where ename='SCOTT')

/*============================================================================*/
--2、查询emp表中 和【员工编号】是7788 的【员工部门相同】的员工编号、姓名、部门编号
select empno,ename,deptno
from emp
where deptno=(select deptno from emp where empno=7788)
-------------------
select *
from (select empno,ename,deptno from emp )
where deptno=(select deptno from emp where empno=7788)

/*============================================================================*/
--3、查询1981年入职的员工中,经理是KING的员工信息
select*
from emp
where to_char(hiredate,'yyyy')=1981
and mgr=(select empno from emp where ename='KING')
-------------------------
select* from emp a
inner join emp b
on a.mgr=b.empno
where to_char(a.hiredate,'yyyy')=1981 and b.ename='KING'

/*============================================================================*/
--4、查询部门所在地是NEW YORK的员工信息(表连接和子查询)
---表连接的方法
select*
from emp a
inner join dept d
on a.deptno=d.deptno
where d.loc='NEW YORK'
----------------------
select*
from emp a,dept d
where a.deptno=d.deptno and loc='NEW YORK'
-----------------------------------------------

你可能感兴趣的:(Oracle,sql,数据库,大数据,oracle)