MYSQL学习笔记之子查询
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MYSQL学习笔记之子查询相关的知识,希望对你有一定的参考价值。
(一)基本介绍
select语句中可以嵌套select语句,被嵌套的select语句被称为子查询。
(二)应用场景
select ...(select ) from ...(select ) where ...(select)..
(三)具体实例
where
实例:找出比最低工资高的员工姓名和工资??
mysql> select ename,sal from emp where sal>min(sal);
ERROR 1111 (HY000): Invalid use of group function
#错误原因:where子句中不能直接使用分组函数
#正确方法如下
#第一步:找出emp表中sal的最小值
mysql> select min(sal) from emp;
+----------+
| min(sal) |
+----------+
| 800.00 |
+----------+
1 row in set (0.00 sec)
#第二步:根据最小值来进行选择和输出符合条件的员工名字和薪水
mysql> select ename,sal from emp where sal>800;
+--------+---------+
| ename | sal |
+--------+---------+
| ALLEN | 1600.00 |
| WARD | 1250.00 |
| JONES | 2975.00 |
| MARTIN | 1250.00 |
| BLAKE | 2850.00 |
| CLARK | 2450.00 |
| SCOTT | 3000.00 |
| KING | 5000.00 |
| TURNER | 1500.00 |
| ADAMS | 1100.00 |
| JAMES | 950.00 |
| FORD | 3000.00 |
| MILLER | 1300.00 |
+--------+---------+
13 rows in set (0.00 sec)
#方法二:通过子查询实现(先执行‘ 子查询 ’,然后再执行‘ 外查询 ’)
mysql> select ename,sal from emp where sal>(select min(sal) from emp);
+--------+---------+
| ename | sal |
+--------+---------+
| ALLEN | 1600.00 |
| WARD | 1250.00 |
| JONES | 2975.00 |
| MARTIN | 1250.00 |
| BLAKE | 2850.00 |
| CLARK | 2450.00 |
| SCOTT | 3000.00 |
| KING | 5000.00 |
| TURNER | 1500.00 |
| ADAMS | 1100.00 |
| JAMES | 950.00 |
| FORD | 3000.00 |
| MILLER | 1300.00 |
+--------+---------+
13 rows in set (0.00 sec)
mysql>
from
实例:找出每个岗位的平均工资的薪资等级
分析:
第一步:根据岗位进行分组,并求出每个分组中的薪水平均值
select job,avg(sal) from emp group by job;
第二步:将上表(假设为 s)和 薪资等级表(s)进行连接,可得目标结果
select
t.* ,s.grade
from
( select job,avg(sal) as avgsal from emp group by job) t
join
salgrade s
on
t.avgsal between s.losal and s.hisal;
#未起别名
mysql> select job,avg(sal) from emp group by job;
+-----------+-------------+
| job | avg(sal) |
+-----------+-------------+
| CLERK | 1037.500000 |
| SALESMAN | 1400.000000 |
| MANAGER | 2758.333333 |
| ANALYST | 3000.000000 |
| PRESIDENT | 5000.000000 |
+-----------+-------------+
5 rows in set (0.00 sec)
#起别名
mysql> select job,avg(sal) as avgsal from emp group by job;
+-----------+-------------+
| job | avgsal |
+-----------+-------------+
| CLERK | 1037.500000 |
| SALESMAN | 1400.000000 |
| MANAGER | 2758.333333 |
| ANALYST | 3000.000000 |
| PRESIDENT | 5000.000000 |
+-----------+-------------+
5 rows in set (0.00 sec)
mysql> select t.* ,s.grade from ( select job,avg(sal) as avgsal from emp group by job) t join salgrade s on t.avgsal between s.losal and s.hisal;
+-----------+-------------+-------+
| job | avgsal | grade |
+-----------+-------------+-------+
| CLERK | 1037.500000 | 1 |
| SALESMAN | 1400.000000 | 2 |
| MANAGER | 2758.333333 | 4 |
| ANALYST | 3000.000000 | 4 |
| PRESIDENT | 5000.000000 | 5 |
+-----------+-------------+-------+
5 rows in set (0.00 sec)
注意:from后面的子查询,可以将子查询的查询结果当做一张临时表。(技巧)
select
案例:找出每个员工的部门名称,要求显示员工名、部门名??
mysql> select e.ename,(select d.dname from dept d where e.deptno = d.deptno) as dname from emp e;
+--------+------------+
| ename | dname |
+--------+------------+
| SMITH | RESEARCH |
| ALLEN | SALES |
| WARD | SALES |
| JONES | RESEARCH |
| MARTIN | SALES |
| BLAKE | SALES |
| CLARK | ACCOUNTING |
| SCOTT | RESEARCH |
| KING | ACCOUNTING |
| TURNER | SALES |
| ADAMS | RESEARCH |
| JAMES | SALES |
| FORD | RESEARCH |
| MILLER | ACCOUNTING |
+--------+------------+
14 rows in set (0.00 sec)
错误情况:
mysql> select e.ename,(select dname from dept) as dname from emp e;
ERROR 1242 (21000): Subquery returns more than 1 row
#说明:dept中的记录个数是四个,并不是一个,所以说在匹配时候会出现错误
mysql> select dname from dept;
+------------+
| dname |
+------------+
| ACCOUNTING |
| RESEARCH |
| SALES |
| OPERATIONS |
+------------+
4 rows in set (0.00 sec)
说明:select后面的子查询只能返回一条结果,如果多于一条就会报错
Union
功能:查询并合并结果集
使用案例:
查询工作岗位是MANAGER和SALESMAN的员工
#方式一
mysql> select ename,job from emp where job=MANAGER or job =SALESMAN;
+--------+----------+
| ename | job |
+--------+----------+
| ALLEN | SALESMAN |
| WARD | SALESMAN |
| JONES | MANAGER |
| MARTIN | SALESMAN |
| BLAKE | MANAGER |
| CLARK | MANAGER |
| TURNER | SALESMAN |
+--------+----------+
7 rows in set (0.00 sec)
#方式二
mysql> select ename ,job from emp where job = MANAGER union select ename,job from emp where job =SALESMAN;
+--------+----------+
| ename | job |
+--------+----------+
| JONES | MANAGER |
| BLAKE | MANAGER |
| CLARK | MANAGER |
| ALLEN | SALESMAN |
| WARD | SALESMAN |
| MARTIN | SALESMAN |
| TURNER | SALESMAN |
+--------+----------+
7 rows in set (0.00 sec)
#方式三
mysql> select ename,job from emp where job in (MANAGER,SALESMAN);
+--------+----------+
| ename | job |
+--------+----------+
| ALLEN | SALESMAN |
| WARD | SALESMAN |
| JONES | MANAGER |
| MARTIN | SALESMAN |
| BLAKE | MANAGER |
| CLARK | MANAGER |
| TURNER | SALESMAN |
+--------+----------+
7 rows in set (0.00 sec)
总结:
union的效率更高一点,对于表的连接来说,每连接一次新表,则匹配的次数满足笛卡尔积,但是union是可以减少匹配次数的,并且在减少匹配次数的同时,还可以完成两个结果集的拼接。
说明:
表a:10条记录
表b:10条记录
表c:10条记录
要求:合并三个表中数据
方式(一)普通的连接:
表a与表b连接: 匹配次数 10*10=100(次)
表a与表c连接: 匹配次数 10*10=100(次)
总匹配次数为: 10 * 10 * 10=1000(次)
方式(二)union连接(乘法变成了加法):
表a与表b连接: 匹配次数 10*10=100(次)
表a与表c连接: 匹配次数 10*10=100(次)
总匹配次数为:100+100=200(次)
union使用说明:
满足条件:
union在进行结果集合并的时候,要求两个结果集的列数(和数据类型)均相同。
Limit
用法如下:
完整用法:limit startIndex ,length;(startIndex是起始下标 length是长度)
缺省用法: limit 5(这里指的是取前五个记录)
功能:
将查询结果的一部分取出来(通常使用在分页查询中)
为什么要分页呢?
分页可以提高用户的体验,如果每一次全部都查出来,用户体验就会降低。
具体实例:
按照薪资降序排列,取出排名在前5名的员工?
mysql> select ename,sal from emp order by sal desc limit 5;
+-------+---------+
| ename | sal |
+-------+---------+
| KING | 5000.00 |
| SCOTT | 3000.00 |
| FORD | 3000.00 |
| JONES | 2975.00 |
| BLAKE | 2850.00 |
+-------+---------+
5 rows in set (0.00 sec)
注意:mysql中limit是在order by之后使用的!!!
取出工资排名在[3,5]名的员工?
#按照工资从高到低的顺序进行排序展示
mysql> select ename,sal from emp order by sal desc ;
+--------+---------+
| ename | sal |
+--------+---------+
| KING | 5000.00 |
| SCOTT | 3000.00 |
| FORD | 3000.00 |
| JONES | 2975.00 |
| BLAKE | 2850.00 |
| CLARK | 2450.00 |
| ALLEN | 1600.00 |
| TURNER | 1500.00 |
| MILLER | 1300.00 |
| WARD | 1250.00 |
| MARTIN | 1250.00 |
| ADAMS | 1100.00 |
| JAMES | 950.00 |
| SMITH | 800.00 |
+--------+---------+
14 rows in set (0.00 sec)
#选出从工资排名表中下标从2(第三个员工)开始连续三个员工的工资
mysql> select ename,sal from emp order by sal desc limit 2,3;
+-------+---------+
| ename | sal |
+-------+---------+
| FORD | 3000.00 |
| JONES | 2975.00 |
| BLAKE | 2850.00 |
+-------+---------+
3 rows in set (0.00 sec)
分页:
如果每页显示三条记录
第1页: limit 0,3 [0,1,2]
第2页: limit 3,3 [3,4,5]
第3页: limit 6,3 [6,7,8]
第4页:limit 9,3 [9,10,11]
每页显示pageSize条记录
第pageNo页: limit (PageNo -1) * pageSize ,pageSize
DQL语句大总结:
select...from...where...group by...having...order by...limit...
执行顺序:
① from
② where
③ group by
④ having
⑤ select
⑥ order by
⑦ limit...
以上是关于MYSQL学习笔记之子查询的主要内容,如果未能解决你的问题,请参考以下文章