20 子查询
什么是子查询?子查询都可以出现在哪里?
select语句当中嵌套select语句,被嵌套的select语句是子查询。
子查询可以出现在哪里?
select
..(select).
from
..(select).
where
..(select).
where子句中使用子查询
案例:找出高于平均薪资的员工信息。
select * from emp where sal > avg(sal); // 错误的写法,where后面不能直接使用分组函数。
select * from emp where sal > (select avg(sal) from emp);
+-------+-------+-----------+------+------------+---------+------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+-------+-----------+------+------------+---------+------+--------+
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
| 7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30 |
| 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 |
| 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 |
| 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
+-------+-------+-----------+------+------------+---------+------+--------+
from后面嵌套子查询
案例:找出每个部门平均薪水的薪资等级
第一步:找出每个部门平均薪水(按照部门编号分组,求sal的平均值)
select deptno,avg(sal) from emp group by deptno;
+--------+-------------+
| deptno | avg(sal) |
+--------+-------------+
| 10 | 2916.666667 |
| 20 | 2175.000000 |
| 30 | 1566.666667 |
+--------+-------------+
第二步:将以上的查询结果当做临时表a,让a表和salgrade表连接,条件是a.avgsal between b.losal and b.hisal。
select a.*,b.grade from (select deptno,avg(sal) as avgsal from emp group by deptno) a join salgrade b on a.avgsal between b.losal and b.hisal;
+--------+-------------+-------+
| deptno | avgsal | grade |
+--------+-------------+-------+
| 30 | 1566.666667 | 3 |
| 10 | 2916.666667 | 4 |
| 20 | 2175.000000 | 4 |
+--------+-------------+-------+
案例:找出每个部门平均的薪水等级。
第一步:找出每个员工的薪水等级。
select a.ename as ename,a.sal as sal,a.deptno as deptno,b.grade as grade from emp a join salgrade b on a.sal between b.losal and b.hisal;
+--------+---------+--------+-------+
| ename | sal | deptno | grade |
+--------+---------+--------+-------+
| SMITH | 800.00 | 20 | 1 |
| ALLEN | 1600.00 | 30 | 3 |
| WARD | 1250.00 | 30 | 2 |
| JONES | 2975.00 | 20 | 4 |
| MARTIN | 1250.00 | 30 | 2 |
| BLAKE | 2850.00 | 30 | 4 |
| CLARK | 2450.00 | 10 | 4 |
| SCOTT | 3000.00 | 20 | 4 |
| KING | 5000.00 | 10 | 5 |
| TURNER | 1500.00 | 30 | 3 |
| ADAMS | 1100.00 | 20 | 1 |
| JAMES | 950.00 | 30 | 1 |
| FORD | 3000.00 | 20 | 4 |
| MILLER | 1300.00 | 10 | 2 |
+--------+---------+--------+-------+
第二步:基于以上结果,继续按照deptno分组,求grade平均值。
select
a.deptno,avg(b.grade)
from
emp a
join
salgrade b on a.sal between b.losal and b.hisal
group by a.deptno;
+--------+--------------+
| deptno | avg(b.grade) |
+--------+--------------+
| 10 | 3.6667 |
| 20 | 2.8000 |
| 30 | 2.5000 |
+--------+--------------+
在select后面嵌套子查询
案例:找出每个员工所在的部门名称,要求显示员工名和部门名。
select
a.ename,(select b.dname from dept b where a.deptno = b.deptno) as dname
from
emp a;
21 union(可以将查询结果集相加)
第一种:找出工作岗位是salesman和manager的员工?
select ename,sal from emp
union
select dname from dept;
ERROR 1222 (21000): The used SELECT statements have a different number of columns