单行子查询
1.什么是子查询?
一条SQL语句含有多个select
-- 引入子查询
-- 查询所有比"CLERK"工资高的员工的信息
-- 步骤1:"CLERK"工资
SELECT sal FROM emp WHERE ename = "CLERK";
-- 步骤2:查询所有工资比2450高的员工的信息
SELECT * FROM emp WHERE sal > 2450;
-- 两次命令解决问题 >> 效率低,第二个命令依托于第一个命令,第一个命令的结果给第二个命令使用,但是
-- 因为第一个命令的结果可能不确定要改,所以第二个命令也会导致修改
-- 将步骤1和步骤2合并 -->> 子查询:
SELECT * FROM emp WHERE sal > (SELECT sal FROM emp WHERE ename = 'CLERK');
-- 一个命令解决问题 -->> 效率高
2.执行顺序:
先执行子查询,再执行外查询
3.不相关子查询:
子查询可以独立运行,称为不相关子查询
4.不相关子查询分类:
根据子查询的结果行数,可以分为单行子查询和多行子查询
-- 单行子查询
-- 查询工资高于平均工资的雇员名字和工资
SELECT ename,sal
FROM emp
WHERE sal > (SELECT AVG(sal) FROM emp);
-- 查询和CLERK同一部门且比他工资低的雇员名字和工资
SELECT ename,sal
FROM emp
WHERE deptno = (SELECT deptno FROM emp WHERE ename = 'CLERK')
AND sal < (SELECT sal FROM emp WHERE ename ='CLERK')
-- 查询职务和SCOTT 相同,比SCOTT雇佣时间早的雇员信息
SELECT * FROM emp
WHERE job = (SELECT job FROM emp WHERE ename = 'SCOTT')
AND hiredate < (SELECT hiredate FROM emp WHERE ename = 'SCOTT')
多行子查询
-- 多行子查询:
-- 1.查询 部门20中职务同部门10的雇员一样的 雇员信息
-- 查询雇员信息
SELECT * FROM emp;
-- 查询部门20中的雇员信息
SELECT * FROM emp WHERE deptno = 20;
-- 查询部门10中的雇员职务
SELECT job FROM emp WHERE deptno = 10;
-- 查询部门20中职务同部门10的雇员一样的雇员信息
SELECT * FROM emp
WHERE deptno = 20
AND job IN (SELECT job FROM emp WHERE deptno = 10);
SELECT * FROM emp
WHERE deptno = 20
AND job = ANY(SELECT job FROM emp WHERE deptno = 10);
-- 2.查询工资比所有的"SALESMAN"都高的雇员的编号,名字和工资
-- 查询雇员的编号,名字,和工资
SELECT empno,ename,sal FROM emp
-- "SALESMAN"的工资:
SELECT sal FROM emp WHERE job = 'SALESMAN'
-- 查询工资比所有的"SALESMAN"都高的雇员的编号,名字和工资
-- 多行子查询:
SELECT * empno,ename,sal
FROM emp
WHERE sal > ALL(SELECT sal FROM emp WHERE job = 'SALESMAN');
-- 单行子查询:
SELECT * empno,ename,sal
FROM emp
WHERE sal > (SELECT MAX(sal) FROM emp WHERE job = 'SALESMAN');
-- 3.查询工资低于任意一个"CLERK"的工资的雇员信息
-- 查询雇员信息
SELECT * FROM emp;
-- 查询工资低于任意一个"CLREK"的工资的雇员信息
SELECT * FROM emp
WHERE sal<ANY(SELECT sal FROM emp WHERE job = 'CLERK')
AND job != 'CLERK'
-- 单行子查询
SELECT * FROM emp
WHERE sal < (SELECT MAX(sal) FROM emp WHERE job='CLERK')
AND job != 'CLERK'
相关子查询
-- 不相关的子查询引入:
不相关的子查询:子查询可以独立运行,先运行子查询,再运行外查询
相关子查询:子查询不可以独立运行,并且先运行外查询,再运行子查询
2.不相关的子查询优缺点:
好处:简单 功能强大(一些使用不相关子查询不能实现或者实现繁琐的子查询,可以使用相关子查询实现)
缺点:稍难理解
-- 查询最高工资的员工(不相关子查询)
SELECT * FROM emp WHERE sal = (SELECT MAX(sal) FROM emp)
-- 查询本部门最高工资的员工 (相关子查询)
-- 方法1:通过不相关子查询实现:
SELECT * FROM emp WHERE deptno = 10 AND sal = (SELECT MAX(sal) FROM emp WHERE deptno = 10)
UNION
SELECT * FROM emp WHERE deptno = 20 AND sal = (SELECT MAX(sal) FROM emp WHERE deptno = 20)
UNION
SELECT * FROM emp WHERE deptno = 30 AND sal = (SELECT MAX(sal) FROM emp WHERE deptno = 30)
-- 缺点:语句比较多,具体到底有多少个部分未知
-- 方法2:相关子查询
SELECT * FROM emp e WHERE sal = (SELECT MAX(sal) FROM emp WHERE deptno = e.deptno) ORDER BY deptno;
-- 查询工资高于其所在岗位的平均工资的那些员工 (相关子查询)
-- 不相关子查询:
SELECT * FROM emp WHERE job = 'CLERK' AND sal >= (SELECT AVG(sal) FROM emp WHERE job = 'CLERK')
UNION ....
-- 相关子查询
SELECT * FROM emp e WHERE sal >= (SELECT AVG(sal) FROM emp e2 WHERE e2.job = e.job)