数据库(oracle)复习day2(子查询) 上午

1 子查询

1.1 为什么要用子查询

问题引出求出谁的工资比 SCOTT高?
解答:因为这个问题不能一步求解,需要分步求解:
1.先求SCOTT的工资

select sal from emp where ename='SCOTT';  ===>求出SCOTT的 工资 为 3000

2.再求比3000大的工资

select * from emp
where sal > 3000;

将上面 两步 合成 一步 就是 所谓的子查询

select * from emp
where sal > (select sal from emp where emp.ename = 'SCOTT');

====>子查询的本质是:select语句的嵌套

2 子查询知识架构

2.1 合理的书写风格

2.2 子查询的 ( ) 不要丢掉

2.3 子查询和主查询可以不是同一张表,只要子查询返回的结果,主查询能用就行

2.3.1 举例说明

eg:查找部门名称是SALES的员工信息
分析思路:1)部门表 和 员工信息表 是两张不同的表。
2)需要在部门表中查到员工编号,然后 拿着员工编号 才能在 员工信息表 中 查到员工的详细信息。
方法1(子查询):

select dept.deptno
from dept
where dept.dname='SALES'

select * 
from emp
where emp.deptno = (select dept.deptno
                    from dept
                    where dept.dname='SALES');

方法2(多表查询):

select e.* 
from emp e , dept d
where e.deptno = d.deptno and d.dname='SALES';

2.3.2 关于SQL优化第3点

子查询检索数据库2次,多表查询检索数据库1次
因此优先用多表查询

2.4 可以在主查询的什么地方放一个子查询

select ...可以放置子查询 (必须要放单行子查询)
from .... 可以放置子查询
where ... 可以放置子查询
group by .... 不
having .... 可以放置子查询 ppt例子
order by ... 不

2.4.1 select后必须放单行子查询

select ename, sal, (select ename from emp where deptno = 10)  十号部门员工
from emp  	 //err

第 1 行出现错误:
ORA-01427: 单行子查询返回多个行

select  ename, sal, (select ename from emp where deptno = 10 and ename='CLARK' )  十号部门一个员工 
from emp;   //right

2.4.2 from后面放置子查询 (重点)

select * 
from emp; //  emp表,表就是一个集合....

-----面试题 要求员工编号员工姓名,只能显示这2列

select * 
from (select empno, ename from emp );

2.5 子查询的分类

1)按照子查询返回的条目数,分为:单行子查询多行子查询
—单行子查询只能用单行比较操作符 ( = < >)
—多行子查询只能用多行比较操作符 (in any all)
in 的用法:
– 查询部门名称 SALES 和 ACCOUNTING 的员工信息
方法1(子查询):

select * 
from emp
where deptno in(select deptno from dept where dname='SALES' or dname='ACCOUNTING')

方法2(多表查询):

select e.*
from emp e, dept d
where e.deptno=d.deptno and (d.dname='SALES' or d.dname='ACCOUNTING'); //注意加括号

– 查询部门名称为 不是 SALES 和 ACCOUNTING 的员工信息
直接在上面语句中加 not 就行
2)按照子查询和主查询的执行顺序来分:一般子子查询相关子查询
1.一般子子查询:子查询把 结果 返回给主查询(一般情况下是这样的)
2.相关子查询:主查询 把 select列中的 参数传递 给 子查询
题目:
– 查询薪水 比30号部门 任意一个员工薪高的员工信息 any
– 查询薪水 比30号部门 所有员工 高的员工信息 all

select *
from emp
where sal > any(select sal from emp where deptno=30) //大于多有的将 any 换成 all

2.6 子查询返回空值的问题

面试题:查询不是经理的员工信息
思路: 先查询是经理的员工信息 再检索所有的不是经理信息

select *
from emp 
where empno in (select mgr from emp);
select * 
from emp
where empno not in (select mgr from emp where mgr is not null);

not in 和in 逻辑关系分析:

The reason is that all conditions that compare a null value result in a null.
Deptno In(10, 20);
解释为: Deptno =10 || deptno=20 ||deptno=null
Deptno not In(10, 20, null);
解释为: Deptno!=10 && Deptno!=20 && deptno!=null

2.7 子查询中一般不使用order by , 但是Top-N问题,子查询必须要用order by

比如:求工资的前三名 分页… M<=x<=N

2.7.1 练习1:找到员工表中工资最高的前三名(Top-N问题)

错误方法:

select rownum, empno, ename, sal
from emp
where rownum <=3    //如果 >3 或者 >=3  返回 没有符合条件的数据
order by sal desc

–1. 有关oracle 伪列 rownum的说明
1 rownum的生成按照oracle的默认顺序生成, 有它自己的生成规则
2 rownum 只能 where rownum <=3 where rownum ❤️
不能 where rownum >=3 where rownum > 3

–2.rownum机制原因分析
rownum 返回的是 结果集的行号
where rownum <=3 这样可以: 有了第一条,才有第二条;1 2 3
rownum >=3 : 第一条记录没有返回,就没有 rownum =2 的记录存在,
rownum =2 记录2若不存在,就没有第三条

练习的正确解答方法:

select rownum, empno, ename, sal 
from (select rownum, empno, ename, sal from emp order by sal desc)
where rownum<=3 

2.7.2 练习2:oracle的分页

—按照员工薪水,降序,求第二页数据 m <= x <= n
即求:5 <=x <=8

select rownum, empno, ename, sal
from (select rownum r, empno, ename, sal from
					 (select empno, ename, sal from emp  order by sal desc) 
					 where rownum<= 8)
where  r>= 5 ;

1.oracle分页思想总结
(内层排序 外层选,需要三层查询)
内:排序。
中:使用rownum选择前n条;并给rownum指定一个别名,以供最外层过滤使用。
外:去掉前m条结果。

2.7.3 练习3:找到 员工表 中 薪水 大于 本部门平均薪水 的员工

分析思路:
1 查找的是员工信息
2 大于 本部门平均薪水 10 ====> 求出 各个部门的平均薪水
select deptno, avg(sal) from emp
group by deptno
3 sal > 本部门员工薪水大于本部门平均薪水 =====条件

方法1:(相关子查询)
----相关子查询概念: 主查询中的参数 通过 别名的方式 ,传递给 子查询语言

select ename, deptno, sal , (select  avg(sal)  from emp where  deptno = e.deptno) avgsal
from emp e
where sal > (select avg(sal) 
			from emp
			where deptno = e.deptno);

方法2:(多表查询)
用到的知识点:
分组 函数 集合别名 多表查询 连接条件 select语句

select e.dname, e.deptno, e.sal, d.avgsal
from emp e (select deptno, avg(sal) avgsal from emp group by deptno) d
where e.deptno=d.deptno and e.sal>d.avgsal

猜你喜欢

转载自blog.csdn.net/qq_40858438/article/details/89183751
今日推荐