Oracle子查询保姆级讲解

子查询

N行N列的概念
根据查询行数与列数的不同,简单分为以下四种查询结果
1.单行单列
无论是在行还是在列上,都只有一个
例:查询整个公司的最高薪资
select max(sal) from EMP;
2.多行查询
查询结果中仅有一列数据,不过行数上不止一行
例:查询10号部门的人员名单
select ename from emp where deptno=10;
3.单行多列
查询结果中仅有一行数据,但是列数上不止一列
例:查询SMITH的姓名,岗位和薪资
select ename,job,sal from emp where ename = ‘SMITH’;

4.多行多列
无论是在行还是在列上,都不止一个
例:查询所有员工的工行、姓名、岗位和部门

select empno,ename,job,deptno from emp;

子查询的概念:
在一个查询语句中,嵌入一条查询语句,该条嵌入式的语句的查询结果成为外层SQL的一部分,即子查询

用途:
1)查询结果作为一个集合,跟在where或having子句中(最多)
1.查询SMITH所在部门的所有员工信息
select deptno from emp where ename=‘SMITH’;
select * from emp where deptno = (select deptno from emp where ename=‘SMITH’);
2.查询BLAKE的带领的员工有那些
select empno from emp where ename=‘BLAKE’;
select * from emp where mgr=(select empno from emp where ename=‘BLAKE’);

3.查询BLAKE的领导手下有那些员工
select mgr from emp where ename = 'BLAKE';
select * from emp where mgr=(select mgr from emp where ename = 'BLAKE');

4.查询与SMITH同部门且薪资相等的员工
select deptno from emp where ename='SMITH';
select * from emp where deptno = (select deptno from emp where ename='SMITH')
											and sal = (select sal from emp where ename='SMITH');

select * from emp where (deptno,sal) in(select deptno,sal from emp where ename='SMITH');
5.查询与SMITH同部门同薪资或与JAMES同部门同薪资的员工
SELECT * from emp where deptno=(select deptno from emp where ename='SMITH')
												and sal = (select sal from emp where ename='SMITH')
												or deptno=(select deptno from emp where ename='JAMES')
												and sal = (select sal from emp where ename = 'JAMES');


select * from emp where(deptno,sal) in(select deptno,sal from emp where ename in('SMITH','JAMES'));


6.查询公司内薪资最高的员工
select max(sal) from emp;
select * from emp where sal=(select max(sal) from emp);
7.查询公司各部门内薪资最高的员工
select max(sal) from emp GROUP BY deptno;
select * from emp where sal in(select max(sal) from emp GROUP BY deptno);
8.查询公司内那个部门的平均工资高于整个公司的平均工资
select avg(sal) from emp;
select deptno from emp GROUP BY deptno HAVING avg(sal)>(SELECT avg(sal) from emp);

9.查询公司内没有员工的部门
SELECT deptno from dept;

子查询用在条件中的注意点:
可以使用N行N列中的每一种情况
主查询与子查询无论在列数还是属性上都要相统一
2)查询结果作为一个数据源,跟在from子句中:
1.查询平均工资最高的部门
SELECT avg(sal) from emp GROUP BY DEPTNO;
SELECT max(avg_sal) from (select avg(sal) avg_sal from emp GROUP BY deptno);

select DEPTNO
from EMP
GROUP BY DEPTNO
HAVING avg(sal) = (select max(avg_sal)
													from (select avg(sal) avg_sal from emp GROUP BY deptno ))

2.查询平均工资最低的岗位
select avg(sal) from emp GROUP BY job;
select min(avg_sal) from (select avg(sal) avg_sal from emp GROUP BY job);

select job from emp GROUP BY job HAVING avg(sal)=(select min(avg_sal) from (select avg(sal) avg_sal from emp GROUP BY job));

子查询的注意点:
1)数据源本身没有行列的限制,所以子查询在该处也可使用N行N列的每种情况
2)子查询作为数据源时,若select子句某字段上出现了函数,则字段只有命别名才可以被主查询引用
3)主查询不关心子查询的结果是如何得到的,只关心查询是什么结果,子查询中的字段能否被正常引用

3)查询结果作为一个常量,跟在select子句中:
1.查询10号部门员工的姓名、岗位、薪资及部门名称和工作地点
select ename,job,sal,
(select dname from dept where deptno=10),
(select loc from dept where deptno=10) from emp where deptno = 10;

2.查询10号部门与20号部门在平均薪资上相差了多少
select 
(select avg(sal) from emp where deptno=10)-
(SELECT avg(sal) from emp where deptno=20) from dual;

子查询作为常量的注意点:
1.查询结果限制在单行单列之间

子查询分类:
1.先前所有举例都有一个共同的特点:子查询部分可以单独执行,即子查询是一个完整的查询语句
2.根据子查询能否单独运行,或根据子查询与主查询是否有语法上的关系,分成相关于查询的非相关子查询。
相关子查询
子查询语句不能独立运行,子查询中牵扯主查询中的一部分内容,主查询只在乎与子查询的关系
非相关子查询
子查询语句能够独立运行,子查询中不牵扯主查询中的任何内容,主查询在乎的是子查询的结果
注意:
1.非相关子查询可以用在任何位置,而相关子查询仅用在where或having子句中作 为条件,且绝大多数情况下两者可以

相关子查询的书写:
1.相关子查询的关键字:
2.EXISTS:对应条件中查询的in
含义:返回结果集为真,执行主查询语句
3.not exiets :对应条件查询中的not in
含义:不返回结果集为真,执行主查询语句

语法:
select T1.COL_LIST
FROM TB_NAME T1
WHERE EXISTS/NOT EXISTS(
SELECT T2,COL_LIST
FROM TB_NAME T2
WHERE T1.COL_NAME = T2.COL_NAME
AND T2.CONDITION

select * from EMP where EXISTS(SELECT * from emp where 1=0);
select * from emp where EXISTS(SELECT 1 from emp where 1=1);

select * from EMP where not EXISTS(SELECT * from emp where 1=0);
select * from emp where not EXISTS(SELECT 1 from emp where 1=1);

子查询的书写步骤:
1.将需求分析成不同的步骤
2.按照步骤的先后分别写成SQL
3.将子查询嵌套到主查询语句中
4.若是需要书写相关子查询,可以先写成非相关子查询,在转成相关子查询
非相关向相关的转化过程
1.主查询的字段及关系替换成 EXISTS
2。主查询与子查询的关联关系写在查询语句中
3.该加表别名的加别名

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值