2018-07-10 08:29:55
思考应用场景
异常数据的测试
6.显示能挣得奖金的雇员的姓名、工资、奖金,并以工资和奖金降序排列。
select ename,sal,comm
from emp
WHERE comm>0
--两列都要desc
order by sal desc,comm desc;
8. 显示姓名中两次出现字母L并且在30部门工作,或者其管理员编号是7782的雇员的姓名。
SELECT ename
FROM emp
--模糊查询
WHERE ename LIKE '%L%L%'
AND deptno=30 OR mgr=7782;
7. 显示雇员的姓名、受雇日期及受雇当天是星期几(列标题为DAY),并以DAY升序排列
SELECT ename,hiredate,TO_CHAR(hiredate,'DAY') "DAY"
FROM EMP
--ORDER BY TO_CHAR(hiredate,'DAY'); 'DAY'是乱序
---'D'按 日,一,二,...六 排序
ORDER BY TO_CHAR(hiredate,'D');
5.查询员工的姓名及其经理编号,要求对于没有经理的显示“No Manager”字符串。
SELECT * FROM emp;
SELECT ename,nvl(to_char(mgr),'No Manager')
FROM emp
4. 编写一个以下面的形式输出的查询:
<employee name> earns <salary> monthly but wants <3 times salary>.
列标题为Dream Salaries。
---列起别名 中间有空格 "Dream Salaries"
SELECT 'employee'||ename || ' earns ' || sal || ' monthly but wants ' || sal * 3 "Dream Salaries"
FROM emp;
--7.显示姓名中第三个字母为A的雇员的姓名。
select ename
FROM emp
where instr(substr(ename,3,1),'A')>0;
(3)显示雇员姓名并以*为指示符代表工资数额(列标题为EMPLOYEE_AND_THEIR_SALARIES),一个指示符代表一百美元,并以工资数额降序排列。
--rpad('原字符',num,'填充的符号') (原字符+填充的符号)=num
SELECT ename || rpad('*',trunc(sal/100),'*') EMPLOYEE_AND_THEIR_SALARIES
FROM emp
ORDER BY sal desc;
一、多表查询
SELECT 列名,列名...
FROM 表名 表的别名,表名 表的别名....
WHERE 条件
ORDER BY 排序字段。。。
1、笛卡尔积:是多张表记录的乘积。
SELECT *
FROM emp,dept
WHERE ename='SMITH';
SELECT * FROM emp;
SELECT * FROM dept;
SELECT ename,emp.deptno,dname
FROM emp,dept;
---*****
2、等值连接,两张表中存在含义相同,值相等的列的
SELECT *
FROM emp,dept
WHERE emp.deptno=dept.deptno;
SELECT a.deptno,ename,dname
FROM emp a,dept b
WHERE A.deptno=b.deptno
ORDER BY A.deptno;
---工资等级
3、不等值连接
SELECT * FROM salgrade;
SELECT *
FROM emp A,salgrade b
--WHERE a.sal >=b.losal and a.sal<=b.hisal;
WHERE sal between losal and hisal;
---查询员工的姓名,员工的部门名称,员工的工资等级
SELECT ename,dname,grade
FROM emp,dept,salgrade
WHERE emp.deptno=dept.deptno AND sal BETWEEN losal AND hisal;
---员工 经理
4、自身连接:
SELECT * FROM emp;
SELECT *
FROM emp A,emp b
---员工的经理编号=经理的员工编号
WHERE a.ename='SMITH' and a.mgr = b.empno;
SELECT *
FROM emp A,emp b
WHERE A.mgr = b.empno;
---查询员工的姓名,员工的部门名称,员工的工资等级,员工对应的领导姓名,领导的部门名称,领导的工资等级
SELECT e.ename 员工姓名,d.dname 员工的部门名称,s.grade 员工的工资等级,m.ename 领导的姓名,md.dname 领导的部门名称,ms.grade 领导的工资等级
FROM emp e,dept d,salgrade s,emp m,dept md,salgrade ms
WHERE e.deptno=d.deptno AND e.sal BETWEEN s.losal AND s.hisal AND e.mgr=m.empno AND m.deptno=md.deptno
and m.sal between ms.losal and ms.hisal;
5、外连接:
SELECT *
FROM emp,dept
---右边的全显示,左边没有的话,用null值填充
WHERE emp.deptno(+)=dept.deptno;
SELECT *
FROM emp,dept
---左边的全显示,左边没有的话,用null值填充
WHERE dept.deptno=emp.deptno(+);
6、SQL1999:
(01)CROSS JOIN:交叉连接,笛卡尔积
语法:table1 CROSS JOIN table2
SELECT *
FROM emp CROSS JOIN dept;
=
SELECT *
FROM emp,dept;
---*****
(02)NATURAL JOIN:自然连接
语法:table1 NATURAL JOIN table2
SELECT *
FROM emp NATURAL JOIN dept;
(03)JOIN...USING(公共列名)
语法:table1 JOIN table2 USING(公共列)
SELECT *
FROM emp JOIN dept USING(deptno);
(4)JOIN...ON 连接条件
语法:table1 join table2 on 连接条件;
SELECT *
FROM emp JOIN dept ON emp.deptno=dept.deptno;
(05)LEFT JOIN...ON 连接条件
语法:table1 LEFT JOIN table2 ON 连接条件
SELECT *
FROM dept left JOIN emp ON emp.deptno=dept.deptno;
(06)RIGHT JOIN...ON 连接条件
语法:table1 RIGHT JOIN table2 ON 连接条件
SELECT *
FROM emp RIGHT JOIN dept ON emp.deptno=dept.deptno;
(07) FULL JOIN...ON 连接条件
语法:table1 full JOIN table2 ON 连接条件
SELECT *
FROM emp e FULL JOIN emp m ON e.mgr = m.empno
ORDER BY e.empno;
二、分组查询
1、分组函数:又称为统计函数,聚合函数
sum():求和
avg():求平均值
MAX():求最大值
MIN():求最小值
count():求个数
*:统计的表的记录数
列名:统计该列不为null的个数
注意:统计时,不对Null值进行处理
SELECT sum(sal),avg(sal),MAX(sal),MIN(sal),count(empno)
FROM emp;
SELECT
FROM
WHERE
GROUP BY 分组字段,分组字段。。。
HAVING 组过滤条件
ORDER BY
---按照职务不同来分组统计工资总和,人数
SELECT job,sum(sal),count(empno)
FROM emp
GROUP BY job;
---查询emp表中不同的职务
SELECT DISTINCT JOB
FROM emp;
SELECT JOB
FROM emp
GROUP BY JOB;
---查询不同的领导工号的个数
SELECT count(distinct mgr)
FROM emp;
---统计各个部门不同职务的员工薪水的总和,平均工资
SELECT deptno,job,sum(sal),avg(sal)
FROM emp
GROUP BY deptno,JOB
ORDER BY deptno;
---统计各个部门不同职务的员工薪水的总和,平均工资,部门名称,职务
SELECT dname,JOB,sum(sal),avg(sal)
FROM emp,dept
WHERE emp.deptno=dept.deptno
GROUP BY dname,JOB
ORDER BY dname;
---统计各个部门不同职务的员工薪水的总和,平均工资,部门编号,部门名称,部门位置,职务
SELECT dept.deptno,dname,loc,JOB,sum(sal),avg(sal)
FROM emp,dept
WHERE emp.deptno=dept.deptno
GROUP BY dept.deptno,dname,loc,JOB
ORDER BY dname;
---统计不同工资等级的员工人数,工资总和,工资平均值
SELECT grade,sum(sal),round(avg(sal),2),count(empno)
FROM emp,salgrade
WHERE sal BETWEEN losal AND hisal
GROUP BY grade;
---统计不同工资等级的员工人数,工资总和,工资平均值,要求员工的 人数要大于2
SELECT grade,sum(sal),round(avg(sal),2),count(empno)
FROM emp,salgrade
WHERE sal BETWEEN losal AND hisal
GROUP BY grade
HAVING count(empno)>2;
---查询各个部门的平均工资大于2000的部门编号和平均工资
SELECT deptno,avg(sal)
FROM emp
GROUP BY deptno
HAVING avg(sal)>2000;
where与having的区别:
WHERE是在分组前进行过滤的,where的后面不能直接使用分组函数做比较
HAVING是在分组后进行过滤的。
3、分组函数的嵌套
---查询部门平均工资最高的平均工资
SELECT MAX(avg(sal))
FROM emp
GROUP BY deptno;
注意:当select后面的分组函数嵌套使用时,SELECT后面不能有任意列名,只能存在嵌套分组函数
第六章课后作业:
1.查询部门平均工资在2500元以上的部门名称及平均工资。
SELECT dname,avg(sal)
FROM emp,dept
WHERE emp.deptno=dept.deptno
GROUP BY dname
HAVING avg(sal)>2500;
2.查询员工岗位中不是以“SA”开头并且平均工资在2500元以上的岗位及平均工资,并按平均工资降序排序。
SELECT JOB,avg(sal)
FROM emp
WHERE upper(JOB) NOT LIKE 'SA%'
GROUP BY JOB
HAVING avg(sal)>2500
ORDER BY 2 desc;
3.查询部门人数在2人以上的部门名称、最低工资、最高工资,并对求得的工资进行四舍五入到整数位。
SELECT dname,round(MIN(sal)),round(MAX(sal))
FROM emp,dept
WHERE emp.deptno=dept.deptno
GROUP BY dname
HAVING count(empno)>2;
4.查询岗位不为SALESMAN,工资和大于等于2500的岗位及每种岗位的工资和。
SELECT JOB,sum(sal)
FROM emp
WHERE upper(JOB)!='SALESMAN'
GROUP BY JOB
HAVING sum(sal)>=2500;
5.显示经理号码和经理姓名,这个经理所管理员工的最低工资,没有经理的KING也要显示,不包括最低工资小于3000的,按最低工资由高到低排序。
SELECT m.empno,m.ename,min(e.sal)
FROM emp e,emp m
WHERE e.mgr=m.empno(+)
GROUP BY m.empno,m.ename
HAVING MIN(e.sal)>=3000
ORDER BY min(e.sal) desc;
6.写一个查询,显示每个部门最高工资和最低工资的差额
SELECT deptno,MAX(sal)-MIN(sal)
FROM emp
GROUP BY deptno;
4.使用ON子句,显示工作在CHICAGO的员工姓名,部门名称,工作地点,薪资等级
select ename,dname,loc ,grade
FROM emp JOIN dept ON emp.deptno =dept.deptno
JOIN salgrade ON sal BETWEEN losal AND hisal
WHERE dept.loc='CHICAGO';
三、子查询
子查询一般用()括起来
子查询出现的位置:select,FROM,WHERE,HAVING
嵌套子查询:一个查询语句中嵌套了另一个查询语句,子查询的语句可以直接运行
单列子查询:子查询的返回结果是单行单列的,经常用在where,HAVING
多行子查询:子查询的返回结果是单列多行的,经常用在where
多列子查询:子查询的返回结果是多行多列的,经常用在from,where
1、单列子查询
---查询与smith相同职务的其它员工信息
SELECT JOB FROM emp WHERE lower(ename)='smith';
SELECT *
FROM emp
WHERE job=(SELECT JOB FROM emp WHERE lower(ename)='smith') and lower(ename)!='smith';
------查询部门平均工资最高的平均工资和部门名称
SELECT MAX(avg(sal))
FROM emp
GROUP BY deptno;
SELECT dname,round(avg(sal),2)
FROM emp JOIN dept ON emp.deptno=dept.deptno
GROUP BY dname
HAVING avg(sal)=(SELECT MAX(avg(sal))
FROM emp
GROUP BY deptno);
2、多行子查询:
集合运算:in
---查询与30部门职务相同的其它部门的员工信息
SELECT distinct JOB FROM emp WHERE deptno=30;
SELECT *
FROM emp
WHERE job in(SELECT distinct JOB FROM emp WHERE deptno=30) and deptno!=30;
ANY:
=ANY:相当于in
SELECT *
FROM emp
WHERE job=any(SELECT distinct JOB FROM emp WHERE deptno=30) and deptno!=30;
>ANY:比子查询返回结果的最小值要大
---查询比10部门的最低工资要高的其它部门员工信息
SELECT *
FROM emp
WHERE sal>ANY(SELECT sal
FROM emp
WHERE deptno=10) and deptno!=10;
<ANY:比子查询返回结果的最大值要小
---查询比20部门的最高工资要低的其它部门的员工信息
SELECT *
FROM emp
WHERE sal<ANY(SELECT sal
FROM emp
WHERE deptno=20) and deptno!=20;
ALL:
=ALL:不存在现象
>ALL:比子查询的返回结果的最大值要大
---查询比20部门所有人薪水都高的员工信息
SELECT *
FROM emp
WHERE sal>all(SELECT sal FROM emp WHERE deptno=20);
<ALL:比子查询的返回结果的最小值要小
---查询比10部门所有人薪水都低的员工信息
SELECT *
FROM emp
WHERE sal<all(SELECT sal FROM emp WHERE deptno=10);
3、多列子查询:
---查询与SCOTT用户工资和职务都匹配的其它员工的信息
SELECT *
FROM emp
WHERE sal=(SELECT sal FROM emp WHERE upper(ename)='SCOTT')
AND JOB=(SELECT JOB FROM emp WHERE upper(ename)='SCOTT')
and upper(ename)!='SCOTT';
SELECT *
FROM emp
WHERE (sal,job) in(SELECT sal,JOB FROM emp WHERE upper(ename)='SCOTT') and upper(ename)!='SCOTT';
---查询部门的名称,部门人数,部门最高工资,部门的最低工资,部门最低工资的员工姓名
SELECT deptno,count(empno),max(sal),min(sal)
FROM emp
GROUP BY deptno;
SELECT dname,t.c,t.ma,t.mi,ename
FROM dept,emp,(SELECT deptno,count(empno) c,max(sal) ma,min(sal) mi
FROM emp
GROUP BY deptno) t
WHERE dept.deptno=emp.deptno and emp.deptno=t.deptno and sal=t.mi;
1.查询比自己职位平均工资高的员工姓名、职位,部门名称,职位平均工资
SELECT JOB,avg(sal)
FROM emp
GROUP BY JOB;
SELECT ename,emp.JOB,dname,sal,t.a
FROM emp,dept,(SELECT JOB,avg(sal) a
FROM emp
GROUP BY JOB) t
WHERE emp.deptno=dept.deptno and emp.job=t.job and sal>t.a;
2.查询职位和经理同员工SCOTT或BLAKE完全相同的员工姓名、职位,不包括SCOOT和BLAKE本人。
SELECT ename,job
FROM emp
WHERE (JOB,mgr) IN (SELECT JOB,mgr FROM emp WHERE upper(ename) IN('SCOTT','BLAKE')) AND upper(ename) NOT IN('SCOTT','BLAKE');
3.查询不是经理的员工姓名
SELECT ename
FROM emp
WHERE empno not in(SELECT distinct mgr FROM emp where mgr is not null);
四、分页查询
1、rownum:伪列:从1开始递增
---查询emp表中的前5行记录
SELECT *
FROM emp
WHERE rownum<=5;
rownum在做比较运算时,只能使用<,<=,不能使用>,>=
----查询emp表中5~10条记录
SELECT rownum r,emp.* FROM emp;
SELECT rownum,t.*
FROM (SELECT ROWNUM r,emp.* FROM emp) t
WHERE t.r between 5 and 10;
---查询emp表中的最后5条记录
SELECT rownum,t.*
FROM (SELECT ROWNUM r,emp.* FROM emp) t
WHERE t.r>(select count(empno) from emp)-5;
---每页显示3条记录,查询第3页的员工信息
SELECT rownum,t.*
FROM (SELECT ROWNUM r,emp.* FROM emp) t
WHERE t.r>(3-1)*3 and t.r<=3*3;
---每页显示3条记录,查询第3页和第5页的员工信息
SELECT rownum,t.*
FROM (SELECT ROWNUM r,emp.* FROM emp) t
WHERE t.r>(3-1)*3 and t.r<=3*3 or t.r>(5-1)*3 and t.r<=5*3;
2、TOPN
---查询工资最高的员工信息
SELECT * FROM EMP ORDER BY sal desc;
SELECT *
FROM (SELECT * FROM EMP ORDER BY sal DESC) t
WHERE rownum<=1;
---查询工资最高的前5位的员工信息
SELECT *
FROM (SELECT * FROM EMP ORDER BY sal DESC) t
WHERE rownum<=5;