一、使用子查询:
① 子查询(内部查询)优先执行
② 将步骤①中查询的结果交给父查询(外部查询)使用,用于确认或取消数据
--一、单行子查询 --1.查询出比JONES雇员工资高的其他雇员 SELECT sal FROM emp WHERE ename = 'JONES';--①查询JONES的工资 SELECT ename, sal FROM emp WHERE sal > (SELECT sal FROM emp WHERE ename = 'JONES');--②查询出比JONES雇员工资高的其他雇员 --2.显示和雇员7369从事相同工作并且工资大于雇员7876的雇员的姓名和工作。 SELECT job FROM emp WHERE empno = 7369;--①查询雇员7369从事的工作 SELECT sal FROM emp WHERE empno = 7876;--②查询雇员7876的工资 SELECT ename, job FROM emp WHERE job = (SELECT job FROM emp WHERE empno = 7369) AND sal > (SELECT sal FROM emp WHERE empno = 7876);--③ --子查询中使用组函数 --3.查询工资最低的员工姓名,岗位及工资 SELECT MIN(sal) FROM emp;--①查询最低工资 SELECT ename,job,sal FROM emp WHERE sal = (SELECT MIN(sal) FROM emp);--② --HAVING子句中使用子查询 --4.查询部门最低工资比20部门最低工资高的部门编号及最低工资 SELECT MIN(sal) FROM emp WHERE deptno = 20;--①查询20部门最低工资 SELECT deptno, MIN(sal) FROM emp GROUP BY deptno HAVING MIN(sal) > (SELECT MIN(sal) FROM emp WHERE deptno = 20);--②
二、子查询包括比较运算符
单行子查询:> >= = < <= <>
多行子查询:IN ANY ALL
--二、多行子查询 --1.查询员工工资为各个部门最低工资的员工信息 SELECT empno, ename, sal FROM emp WHERE sal IN (SELECT MIN(sal) FROM emp GROUP BY deptno); --2.查询是经理的员工姓名,工资 SELECT * FROM emp WHERE empno IN(SELECT DISTINCT mgr FROM emp); --3.查询员工工资为各个部门最低工资的员工信息(使用ANY) SELECT empno, ename, sal FROM emp WHERE sal = ANY(SELECT MIN(sal) FROM emp GROUP BY deptno);--相当于IN --4.查询部门编号不为10,且工资比10部门【任意】一名员工工资高的员工编号,姓名,职位,工资 SELECT empno, ename, job, sal FROM emp WHERE deptno <> 10 AND sal > ANY (SELECT sal FROM emp WHERE deptno = 10); --5.查询部门编号不为10,且工资比10部门【所有】一名员工工资低的员工编号,姓名,职位,工资 SELECT empno, ename, job, sal FROM emp WHERE deptno <> 10 AND sal < ALL (SELECT sal FROM emp WHERE deptno = 10);
三、多列子查询
功能:返回多行多列
通常用多行运算符:IN
--三、多列子查询 --1.查询出和1981年入职的【任意】一个员工的部门和职位【完全相同】员工姓名、部门、职位、入职日期,不包括1981年入职员工 SELECT * FROM emp WHERE hiredate BETWEEN '1-1月-81' AND '31-12月-81';--查询1981年入职的员工 SELECT * FROM emp WHERE TO_CHAR(hiredate,'yyyy') = '1981';--查询1981年入职的员工 SELECT * FROM emp WHERE SUBSTR(hiredate,-2) = '81';--查询1981年入职的员工 SELECT * FROM emp WHERE EXTRACT(YEAR FROM hiredate) = '1981';--查询1981年入职的员工 SELECT ename, deptno, job, hiredate--成对比较 FROM emp WHERE (deptno, job) = ANY (SELECT deptno, job FROM emp WHERE SUBSTR(hiredate, -2) = '81') AND SUBSTR(hiredate, -2) <> '81'; --2.查询出和1981年入职的【任意】一个员工的【部门或职位相同】员工姓名、部门、职位、入职日期,不包括1981年入职员工 SELECT DISTINCT deptno FROM emp WHERE TO_CHAR(hiredate,'yyyy') = '1981';--①1981年入职员工的部门 SELECT DISTINCT job FROM emp WHERE SUBSTR(hiredate, -2) = '81';--②1981年入职员工的职位 SELECT DISTINCT ename, deptno, job, hiredate--不成对比较 FROM emp WHERE (deptno IN (SELECT DISTINCT deptno FROM emp WHERE TO_CHAR(hiredate, 'yyyy') = '1981') OR job IN (SELECT DISTINCT job FROM emp WHERE SUBSTR(hiredate, -2) = '81')) AND EXTRACT(YEAR FROM hiredate) <> '1981';
四、子查询中的NULL值
一般格式:
[列名 | 表达式] IS NOT NULL
作用:
限制列名或表达式不能为空
--四、子查询中的NULL值 --1.查询不是经理的员工姓名,工资 SELECT ename,sal FROM emp WHERE empno NOT IN(SELECT DISTINCT mgr FROM emp WHERE mgr IS NOT NULL);
五、在FROM子句使用子查询
一般格式:
SELECT [列名 | *] FROM 子查询 WHERE 限制条件;
--五、在FROM子句中使用子查询 --1.查询比自己部门平均工资高的员工姓名、工资、部门编号、部门平均工资 SELECT deptno,AVG(sal) FROM emp GROUP BY deptno;--查询各部门的平均工资 SELECT ename,sal,e.deptno,avgsal FROM emp e,(SELECT deptno,AVG(sal) avgsal FROM emp GROUP BY deptno) s WHERE e.deptno = s.deptno AND sal > avgsal;
六、ROWNUM伪列
注意: 伪列,永远从1开始,rownum只能执行<、<=运算,不能执行>、>=或一个区间运算Between..And等
--六、TOP-N查询 --1.查询工资最高的三个员工的信息 SELECT ROWNUM,e1.* FROM (SELECT emp.* FROM emp WHERE sal IS NOT NULL ORDER BY sal DESC) e1 WHERE ROWNUM <= 3; --2.查询工资最低的三个员工的信息 SELECT ROWNUM,e1.* FROM (SELECT emp.* FROM emp WHERE sal IS NOT NULL ORDER BY sal) e1 WHERE ROWNUM <= 3;
七、数据库的分页查询
开始下标:(当前页码-1)*每页显示条数 + 1
结束下标:每页显示条数 * 当前页码
--七、数据库分页查询 --1.查询第一页数据 SELECT ROWNUM,e.* FROM emp e WHERE ROWNUM <= 5; --2.查询第二页数据 SELECT e1.* FROM (SELECT ROWNUM rn,e.* FROM emp e WHERE ROWNUM <= 10) e1 WHERE e1.rn >= 6; --效率高,仅查询10条 SELECT e1.* FROM (SELECT ROWNUM rn,e.* FROM emp e) e1 WHERE e1.rn <= 10 AND e1.rn >= 6; --效率低,永远查询所有数据 --3.查询第三页数据 SELECT e1.* FROM (SELECT ROWNUM rn,e.* FROM emp e WHERE ROWNUM <= 15) e1 WHERE e1.rn >= 11; --效率高 SELECT e1.* FROM (SELECT ROWNUM rn,e.* FROM emp e) e1 WHERE e1.rn <= 15 AND e1.rn >= 11; --效率低 --公用的SQL分页查询语句 SELECT e1.* FROM (SELECT ROWNUM rn,e.* FROM emp e WHERE ROWNUM <= &end) e1 WHERE e1.rn >= &begin; SELECT e1.* FROM (SELECT ROWNUM rn,e.* FROM emp e WHERE ROWNUM <= (每页显示条数 * 当前页码)) e1 WHERE e1.rn >= (当前页码-1)*每页显示条数 + 1); SELECT e1.* FROM (SELECT ROWNUM rn,e.* FROM emp e) e1 WHERE e1.rn <=(每页显示条数 * 当前页码) AND e1.rn >= (当前页码-1)*每页显示条数 + 1); --数据分页前,先排序 --1.根据入职日期降序排序后,再分页 SELECT * FROM (SELECT ROWNUM rn, e1.* FROM (SELECT emp.* FROM emp order by hiredate desc) e1 WHERE ROWNUM <= 10) e2 WHERE e2.rn >= 6;