Oracle基本查询语法
本文含:多表查询/子查询/集合运算
1.多表查询
主要就是连接条件: nge表至少有n-1个连接条件
1.1连接类型: 1.
等值连接
2.
不等值连接
3
. 外连接
4.
自连接
举例: 等值连接 :查询员工信息:员工号 姓名 月薪 部门名称
select e.empno,e.ename,e.sal,d.dname from emp e,dept d where e.deptno=d.deptno;
不等值连接: 查询员工信息:员工号 姓名 月薪 工资级别
select e.empno,e.ename,e.sal,s.grade from emp e,salgrade s
where
e.sal between s.losal and s.hisal;
3.外连接:
左外连接:当where e.deptno=d.deptno不成立的时候,等号左边的表任然包含在最后的结果中
写法:where e.deptno=d.deptno(+)
右外连接:当where e.deptno=d.deptno不成立的时候,等号右边的表任然包含在最后的结果中
写法:where e.deptno(+)=d.deptno
举例:按部门统计员工人数:部门号 部门名称 人数
希望:对于某些不成立的记录(40号部门没有员工,条件不成立),任然希望包含在最后的结果中
1.select d.deptno 部门号,d.dname 部门名称,count(e.empno) 人数 from emp e,dept d
where e.deptno(+)=d.deptno group by d.deptno,d.dname;
4.自连接
通过表的别名,将同一张表视为多张表 ,
自连接不适合操作大表, 本质上是多表查询, 查询产生的
笛卡尔基中符合条件的 ,
有性能问题
举例: //查询员工信息: 员工姓名和其老板姓名
select e.ename 员工姓名,b.ename 老板姓名 from
emp e,emp b where e.mgr=b.empno;
层次查询:本质属于单表查询,不会产生笛卡尔基
上下级关系 树体系图
//同样 查询员工信息: 员工姓名和其老板姓名
根据数图, 有: 上一级的员工号=下一级的老板号 ,遍历树,有起始条件,和连接条件
select
level,empno,ename,mgr from emp
connect by prior empno=mgr
start with
mgr is null order by 1;
2.子查询:
子查询所要解决的问题:不能一步求解的问题!
语法:select 语句的嵌套
1.单行子查询
:如果子查询只返回一行记录,就是单行子查询
单行操作符: = , > , >=,<,<=,<>
2.多行子查询:
如果子查询返回多行记录,就是多行子查询
多行操作符: in(set) , any , all
如:查询工资比SCOTT高的员工信息,分两步
1.查询SCOTT的工资: select sal from emp where ename='SCOTT';
2. 查询比3000高的员工: select * from emp where sal>3000;
子查询: select * from emp where sal > (select sal from emp where ename='SCOTT');
//多行子查询
1.in 在集合中
select * from emp where deptno
in (select deptno from dept where dname='SALES'
or dname='ACCOUNTNG');
select e.* from emp e,dept d
where e.deptno=d.deptno
and (d.dname='SALES'
or d.dname='ACCOUNTING');
2.any: 和集合中任意一个值比较
//查询工资比30号部门任意一个员工高的员工信息
select * from emp where sal >
any (select sal from emp where deptno=30);
//大于集合任意一个值,只需要大于集合最小值即可
select * from emp where sal > (select min(sal) from emp where deptno=30)
3. all:和集合中的所有值比较
//查询工资比30号部门所有员工高的员工信息
select * from emp where sal > all (select sal from emp where deptno=30);
或 select * from emp where sal > (select max(sal) from emp where deptno=30)
注意的问题:
1. 要有括号
2.合理的书写风格
3.可以在主查询的where ,select, having ,from后面都可以使用子查询
select 语句后面使用子查询,只能使用单行子查询,即只允许返回一条记录
4.不可以在
group by后面使用子查询
5.强调from后面的子查询
6.主查询和子查询可以不是同一张表;只要子查询返回的结果主查询可以使用 即可
7.一般不在子查询中排序;但在
top-n分析问题中,必须对子查询排序
8.一般先执行子查询 再执行主查询;但相关子查询例外
9.单行子查询只能使用单行操作符;多行子查询只能使用多行操作
主查询可以有多个子查询,即1:n关系,子查询可以嵌套用,最多855层
10.子查询中的null ,为什么集合中若有空值,不能用not in(10,20,null) 可以用in( );
举例:和上面序号对应
3. //select 语句后面使用子查询,只能使用单行子查询,即只允许返回一条记录
select empno,ename,sal,
(select job from emp where empno=7839) 第四列 from emp;
//按部门分组查询最低工资,且最低工资大于10号部门的最低工资才显示
select deptno ,min(sal) from emp group by deptno having min(sal) >
(select min(sal) from emp where deptno = 10);
//查询员工号,姓名,月薪 ,年薪
select * from (select empno,ename,sal , sal*12 年薪 from emp );
6.查询部门名称是sales的员工
select * from emp where deptno = (select deptno from dept where dname='SALES');//子查询方式
select e.* from emp e,dept d where e.deptno = d.deptno and d.dname='SALES';//多表查询方式
7.Top-n分析: 找出员工工资表的前三名
8.一般先执行子查询 再执行主查询;但
相关子查询例外
9.单行子查询只能使用单行操作符;多行子查询只能使用多行操作
//查询工资最低的员工的职位和薪水
select ename,job,sal from emp where sal =(select min(sal) from emp);
//下面是非法的,因为
多行子查询使用
单行比较符
select ename from emp where
sal = (select min(sal) from emp group
by deptno);错误
10. 单行子查询空值问题 不能贸然使用 = 或 != ,因为后面返回null就永远不成立
select ename, job from emp where
job=
(select job from emp where ename='mike')
//子查询可能返回null ,而判断是否为空,不能使用 = 或者 !=
多行子查询中的null:
集合有空值,不能用not in 可以用in
//查询不是领导的员工
select * from emp where empno not in (select mgr from emp);
//错误写法
select * from emp where empno not in (select mgr from emp where mgr is not null);
//正确
3.集合运算
1.集合运算符:
union/union all 并集
union:公共部分要一次; 而union all 要两次,没有公共部分,二者相同
intersect 交集
minus 差集
注意: 使用集合运算,select语句可以相加,也可以相减
1.
参与运算的集合必须
列数相同 且类型一致
2. 采用第一个集合作为最后的表头
3. order by 永远在最后
4. 括号 ,可以改变执行顺序
//查询10和20号部门的员工
1. select * from emp where deptno in (10,20);
2. select * from emp where deptno=10 or deptno=20;
3.集合运算
select * from emp where deptno=10
union select * from emp where deptno=20;
举例:
并集1.
参与运算的集合必须列数相同 且类型一致
select deptno,job,sum(sal) from emp group by deptno,job
union
select deptno,
to_char(null),sum(sal) from emp group by deptno
union
select
to_number(null), to_char(null), sum(sal) from emp;
//由于列数不一致,需要手动补齐列数,一般用null,转换成对应数据类型
交集:
//显示薪水同时位于700~1300级别和1201~1400级别的员工
select ename,sal from emp where sal between 700 and 1300
intersect select ename,sal from emp where sal between 1201 and 1400;
差集
//显示薪水位于700~1300但不位于1201~1400级别的员工
select ename,sal from emp where sal between 700 and 1300
minus select ename,sal from emp where sal between 1201 and 1400;