1、 单行函数:
· 字符串函数:
|- 转大写:字符串 UPPER(列 | 字符串);
|- 转小写:字符串 LOWER(列 | 字符串);
|- 字符串截取:字符串 SUBSTR(列 | 字符串,开始点 [,截取长度]),起始索引为1;
· 数值函数:
|- 四舍五入:数字 ROUND(列 | 数字);
|- 求模:数字 MOD(列1 | 数字1 , 列2 | 数字2);
· 日期函数:
|- 日期的基本公式:
|- 日期 + 数字 = 日期(若干天之后的日期);
|- 日期 - 数字 = 日期(若干天之前的日期);
|- 日期 - 日期 = 数字(两个日期之间所差的天数);
|- 两个日期间的总月数:数字 MONTHS_BETWEEN(日期1,日期2);
· 转换函数:
|- 日期或数字转换为字符串:字符串 TO_CHAR(列 | 日期 | 数字,转换格式);
|- 日期时间:年(yyyy)、月(mm)、日(dd)、时(hh24)、分(mi)、秒(ss);
|- 数字描述:任意一位数字(9)、本地货币(L);
· 通用函数:
|- 处理NULL:数字 NVL(列,默认值);
|- 多值判断:数据 DECODE(列 | 数值,匹配内容1,显示内容1,... [,默认值]);
2、 多表查询:不管你怎样进行处理,多表查询永远都会存在有笛卡尔积,是不可能取消掉的,能够处理的只是取消掉显示中的笛卡尔积。表越多笛卡尔积就越大;
· 只有具备关联的表才可能会进行多表查询,而关联的条件可能是列,也可能是自己设置的范围;
· 表的连接方式:
|- 内连接(等值连接):不满足条件的一概不显示;
|- 外连接(左外连接、右外连接、全外连接),在oracle中使用“(+)”;
|- 左外连接:字段 = 字段(+);
|- 右外连接:字段(+) = 字段;
· SQL:1999语法实现表的连接操作,所有的数据库通用的做法;
· 集合操作:UNION、UNION ALL、MINUS、INTESECT,若干个查询返回的结构必须完全相同;
3、 分组统计查询:如果在列上存在有重复数据那么才会考虑进行分组查询操作;
|- 统计函数:COUNT()、AVG()、SUM()、MAX()、MIN();
|- 利用GROUP BY子句可以实现分组的操作,但是对于分组有若干限制:
|- 如果不使用GROUP BY子句分组,则SELECT子句之中只能够出现统计函数;
|- 如果使用了GROUP BY子句,则SELECT子句里面可以使用分组字段或者是统计函数;
|- 统计函数允许嵌套,嵌套之后的SELECT子句里面不允许出现任何字段,包括分组字段。
|- GROUP BY子句是在WHERE子句之后执行的,所以WHERE子句无法使用统计函数,对分组后的数据进行过滤,则可以使用HAVING子句。
1子查询返回单行单列,统计出公司的最低工资
select * from emp
where sal=(select min(sal) from emp);
2子查询返回单行多列,查询出与SCOTT工资相同,职位相同的所有雇员信息
select sal,job from emp where ename='SCOTT' ;
select * from emp
where (sal,job)=(
select sal,job from emp where ename='SCOTT')
and ename<>'SCOTT';
IN操作指的是内容可以在指定的范围之中存在
select * from emp
where sal in(
select sal from emp where job='MANAGER');
对于IN操作还可以使用NOT IN进行
select * from emp
where sal not in(
select sal from emp where job='MANAGER');
曾经说过一个问题, NOT IN不能够为null
select * from emp
where comm not in(
select comm from emp);
对于ANY操作实质上有三种子语法:=ANY:功能上与IN是完全没有任何区别的
select * from emp
where sal=any(
select sal from emp where job='MANAGER');
>ANY:比子查询返回的最小的内容要大
select * from emp
where sal>any(
select sal from emp where job='MANAGER');
<ANY:比子查询中返回最大的值要小
select * from emp
where sal<any(
select sal from emp where job='MANAGER');
ALL操作有两种使用形式, >ALL:比子查询返回最大的值要大
select * from emp
where sal > all(
select sal from emp where job='MANAGER');
<ALL:比子查询中返回的最小的值还要小
select * from emp
where sal < all(
select sal from emp where job='MANAGER');
exists()判断,如果现在子查询有数据返回(不管什么数据)就表示条件满足,那么就可以显示出数据,否则不显示。deptno=99不存在
select * from emp
where exists(
select * from emp where deptno=99);
select * from emp
where exists(
select * from emp where empno='7839');
如果要使用到HAVING那么必须要结合GROUP BY子句,而如果要使用GROUP BY子句就一定要分组
3要求统计出所有高于公司平均工资的部门编号、平均工资、部门人数
select deptno,count(*),avg(sal)
from emp
group by deptno;
select deptno,count(*),avg(sal)
from emp
group by deptno
having avg(sal)>(
select avg(sal) from emp);
4查询每个雇员的编号、姓名、职位、部门名称
select e.empno,e.ename,e.job,d.dname
from emp e,dept d
where e.deptno=d.deptno;
而现在可以利用子查询,在SELECT子句里面简化操作
select e.empno,e.ename,e.job,
(select dname d from dept d where d.deptno=e.deptno)
from emp e;
5查询出每个部门的编号、名称、位置、部门人数、平均工资
select d.deptno,d.dname,d.loc,count(*),avg(sal)
from emp e,dept d
where e.deptno(+)=d.deptno
group by d.deptno,d.dname,d.loc;
但是除了以上的方式之外,也可以利用子查询完成。
首先dept是一张数据表,但是对于数据的统计查询,也可以将其定义为一张表
select deptno,count(*),avg(sal)
from emp
group by deptno;
此时的查询返回的是一个多行多列的数据,那么只要是多行多列,就一定可以在FROM子句中出现
select d.deptno,d.dname,d.loc,temp.count,temp.avg
from dept d,(
select deptno,count(empno) count,avg(sal) avg
from emp
group by deptno) temp
where d.deptno=temp.deptno(+);
6复杂查询:第一步:找到30部门所有雇员的薪金
select sal from emp where deptno=30;
使用“>ALL”:比子查询返回最大的值要大
select e.ename,e.sal
from emp e
where e.sal>all(
select sal from emp where deptno=30);
要找到部门的信息,自然在FROM子句之后引入dept表,而后要消除笛卡尔积。用内连接
select e.ename,e.sal,d.dname
from emp e,dept d
where e.sal > all(
select sal from emp where deptno=30)
and e.deptno=d.deptno;
· 如果要进行部门的人数统计,那么一定要按照部门分组;
· 在使用分组的时候,SELECT子句只能够出现分组字段与统计函数。
于是此时就出现了一个矛盾,因为SELECT子句里面有其他的字段,所以不可能直接使用GROUP BY分组,所以可以考虑利用子查询分组,即:在FROM子句之后使用子查询先进行分组统计,而后将临时表继续采用多表查询操作
select e.ename,e.sal,d.dname,temp.count
from emp e,dept d,(
select deptno dno,count(empno) count
from emp
group by deptno) temp
where e.sal > all(
select sal from emp where deptno=30)
and e.deptno=d.deptno
and d.deptno=temp.dno;
7列出与“SCOTT”从事相同工作的所有员工及部门名称,部门人数,领导姓名
第一步:没有SCOTT的工作就无法知道那个雇员满足条件,需要找到SCOTT的工作
select job from emp where ename='SCOTT';
第二步:以上的查询返回的是单行单列,所以只能够在WHERE或者是HAVING中使用,那么根据现在的需求肯定在WHERE中使用,对所有的雇员信息进行筛选
select e.empno,e.ename,e.job
from emp e
where job=(
select job from emp where ename='SCOTT');
第三步:如果不需要重复信息,那么可以删除SCOTT
select e.empno,e.ename,e.job
from emp e
where job=(
select job from emp where ename='SCOTT')
and e.ename<>'SCOTT';
第四步:部门名称只需要加入dept表即可
select e.empno,e.ename,e.job,d.dname
from emp e,dept d
where job=(
select job from emp where ename='SCOTT')
and e.ename<>'SCOTT'
and e.deptno=d.deptno;
第五步:此时的查询不可能直接使用GROUP BY进行分组,所以需要使用子查询实现分组
select e.empno,e.ename,e.job,d.dname,temp.count
from emp e,dept d,(
select deptno dno,count(ename) count
from emp
group by deptno) temp
where job=(
select job from emp where ename='SCOTT')
and e.ename<>'SCOTT'
and e.deptno=d.deptno
and d.deptno=temp.dno;
第六步:找到对应的领导信息,直接使用自身关联
select e.empno,e.ename,e.job,d.dname,temp.count,m.ename
from emp e,dept d,(
select deptno dno,count(empno) count
from emp
group by deptno) temp,emp m
where e.job=(
select job from emp where ename='SCOTT')
and e.ename<>'SCOTT'
and e.deptno=d.deptno
and d.deptno=temp.dno
and e.mgr=m.empno;
8列出薪金比“SMITH”或“ALLEN”多的所有员工的编号、姓名、部门名称、其领导姓名,部门人数,平均工资、最高及最低工资
|- 雇员与部门:emp.deptno=dept.deptno;
|- 雇员与领导:emp.mgr=memp.empno
第一步:知道“SMITH”或“ALLEN”,这个查询返回多行单列(WHERE中使用)
select sal from emp where ename in('SMITH','ALLEN');
第二步:现在应该比里面的任意一个多即可,但是要去掉两个雇员。由于是多行单列子查询,所以使用>ANY完成
select e.empno,e.ename,e.sal
from emp e
where e.sal>any(
select sal from emp
where ename in('SMITH','ALLEN'))
and e.ename not in('SMITH','ALLEN');
第三步:找到部门名称
select e.empno,e.ename,e.sal,d.dname
from emp e,dept d
where e.sal>any(
select sal
from emp
where ename in('SMITH','ALLEN'))
and e.ename not in('SMITH','ALLEN')
and e.deptno=d.deptno;
第四步:找到领导信息
select e.empno,e.ename,e.sal,d.dname,m.ename
from emp e,dept d,emp m
where e.sal>any(
select sal from emp
where ename in('SMITH','ALLEN'))
and e.ename not in('SMITH','ALLEN')
and e.deptno=d.deptno
and e.mgr=m.empno(+);
第五步:部门人数,平均工资、最高及最低工资。整个查询里面不能够直接使用GROUP BY,所以现在应该利用子查询实现统计操作
select e.empno,e.ename,e.sal,d.dname,m.ename,temp.count,temp.avg,temp.max,temp.min
from emp e,dept d,emp m,(
select deptno dno,count(empno) count,avg(sal) avg,max(sal) max,min(sal)min
from emp
group by deptno) temp
where e.sal>any(
select sal from emp
where ename in('SMITH','ALLEN'))
and e.ename not in('SMITH','ALLEN')
and e.deptno=d.deptno
and e.mgr=m.empno(+)
and d.deptno=temp.dno;
9列出受雇日期早于其直接上级的所有员工的编号、姓名、部门名称、部门位置、部门人数。
select e.empno,e.ename
from emp e,emp m
where e.mgr=m.empno(+) and e.hiredate<m.hiredate;
第二步:找到部门信息
select e.empno,e.ename,d.dname,d.loc
from emp e,dept d,emp m
where e.mgr=m.empno(+) and e.hiredate<m.hiredate
and e.deptno=d.deptno;
第三步:统计部门人数
select e.empno,e.ename,d.dname,d.loc,temp.count
from emp e,emp m,dept d,(
select deptno dno,count(empno) count
from emp
group by deptno) temp
where e.mgr=m.empno(+) and e.hiredate<m.hiredate
and e.deptno=d.deptno
and d.deptno=temp.dno;
10列出所有“CLERK”(办事员)的姓名及其部门名称,部门的人数,工资等级
· 确定要使用的数据表:
|- emp表:姓名;
|- dept表:部门名称;
|- emp表:统计部门人数;
|- salgrade表:得到工资等级。
· 确定已知的关联字段:
|- 雇员与部门:emp.deptno=dept.deptno;
|- 雇员与工资等级:emp.sal BETWEEN salgrade.losal AND salgrade.hisal
第一步:找到所有办事员的信息
select e.ename from emp e where e.job='CLERK';
第二步:找到部门名称
select e.ename,d.dname
from emp e,dept d
where e.job='CLERK' and e.deptno=d.deptno;
第三步:统计出部门人数
select e.ename 姓名,d.dname dept表部门名称,temp.人数
from emp e,dept d,(
select deptno dno,count(empno) 人数
from emp
group by deptno) temp
where e.job='CLERK' and e.deptno=d.deptno
and d.deptno=temp.dno;
第四步:找到工资等级
select e.ename,d.dname,temp.count,s.grade
from emp e,dept d,(
select deptno dno,count(empno) count
from emp
group by deptno) temp,salgrade s
where e.job='CLERK' and e.deptno=d.deptno
and d.deptno=temp.dno
and e.sal between s.losal and s.hisal;
-----------------------------------------
select e.ename 姓名,d.dname dept表部门,temp.人数,s.grade 工资等级
from emp e,dept d,(
select deptno dno,count(empno) 人数
from emp
group by deptno) temp,salgrade s
where e.job='CLERK' and e.deptno=d.deptno
and d.deptno=temp.dno
and e.sal between s.losal and s.hisal;