当一个查询嵌套了另一个查询,把嵌套在里面的查询先执行的查询就称为子查询。
当一个查询要完成时,需要用到另一个查询的结果才能继续操作,那么这个查询的select就可以用子查询来方式编写。
测试表一 t_employee(员工表)
下面的栗子都是以此表数据为基准进行子查询操作。
mysql> select * from t_employee;
+-----+----------+--------+---------+------------+------------+--------------+------+
| eid | ename | gender | salary | birthday | hiredate | native_place | did |
+-----+----------+--------+---------+------------+------------+--------------+------+
| 1 | 林大侠 | 男 | 8000.46 | 1980-10-08 | 2011-07-28 | 浙江 | 1 |
| 2 | 刘猪猪 | 男 | 7000.67 | 1984-08-03 | 2015-07-03 | 河北 | 1 |
| 3 | 猪猪侠 | 男 | 8000 | 1985-04-09 | 2014-07-01 | 陕西 | 1 |
| 4 | 李大象 | 男 | 9456 | 1986-09-07 | 2015-08-08 | 黑龙江 | 3 |
| 5 | 周泡泡 | 男 | 8567 | 1978-08-02 | 2015-01-01 | 吉林 | 1 |
| 6 | 斯瓦辛格 | 男 | 12000 | 1985-04-03 | 2015-02-02 | 内蒙古 | 1 |
| 7 | 乐乐 | 男 | 15700 | 1982-08-02 | 2015-03-03 | 新疆 | 1 |
| 8 | 周大龙 | 男 | 9000 | 1983-03-02 | 2015-01-06 | 西藏 | 1 |
| 9 | 李峰 | 男 | 7897 | 1984-09-01 | 2015-04-01 | 天津 | 1
| 10 | 韩噶 | 男 | 8789 | 1989-04-02 | 2014-09-03 | 江苏 | 1 |
| 11 | 黄大大 | 男 | 15678 | 1983-05-07 | 2014-04-04 | 安徽 | 1 |
| 12 | 范冰 | 女 | 8909 | 1986-04-02 | 2014-02-08 | 贵州 | 1
| 13 | 李冰 | 女 | 18760 | 1987-04-09 | 2015-06-07 | 四川 | 1 |
| 14 | 邻娜 | 女 | 18978 | 1990-01-01 | 2015-09-05 | 成都 | 2 |
| 15 | 董号 | 女 | 8978 | 1987-05-05 | 2015-08-04 | 云南 | 2 |
| 16 | 汤唯俄 | 女 | 9878 | 1988-03-06 | 2015-03-06 | 宁夏 | 2 |
| 17 | 李诗圣 | 女 | 9000 | 1990-08-09 | 2013-06-09 | 河南 | 2 |
| 18 | 凯记卡 | 女 | 16788 | 1978-09-04 | 2013-04-05 | 福建 | 4 |
| 19 | 周积极 | 女 | 7876 | 1988-06-13 | 2014-04-07 | 广西 | 4 |
| 20 | 张章子 | 女 | 15099 | 1989-12-11 | 2015-08-04 | 广东 | 5 |
| 21 | 白百客 | 女 | 9787 | 1989-09-04 | 2014-06-05 | 海南 | 5 |
| 22 | 刘化环 | 男 | 130990 | 1990-11-09 | 2016-08-09 | 北京 | 3 |
| 23 | 陈龙 | 男 | 130990 | 1990-02-04 | 2016-05-09 | 上海 | 1 |
| 24 | 迪丽热 | 女 | 10289 | 1990-04-01 | 2017-02-06 | 北京 | 5 |
| 25 | 姚杰杰 | 女 | 9087 | 1989-08-01 | 2017-09-01 | 北京 | 5 |
+-----+----------+--------+---------+------------+------------+--------------+------+
25 rows in set (0.00 sec)
测试表二 t_department(部门表)
mysql> select * from t_department;
+-----+--------+------------------+
| did | dname | description |
+-----+--------+------------------+
| 1 | 开发部 | 负责后台开发工作 |
| 2 | 前端部 | 负责前端开发工作 |
| 3 | 运维部 | 负责服务运营工作 |
| 4 | 客户部 | 负责需求服务工作 |
| 5 | 测试部 | 负责测试工作 |
+-----+--------+------------------+
5 rows in set (0.00 sec)
(1)where型子查询:即把内层的sql语句查询的结果作为外层sql查询的条件。要求子查询的结果是“单个值”或“一列多行”。
①子查询语句要包含在括号中“()”
②一般将子查询放在比较条件的右侧【位置】
③单行操作符对应单行子查询,多行操作符对应多行子查询【操作符-区别】
单行操作符:右边子查询必须返回的是单个值,单行比较运算符(=(等于)、>(大于)、>=(大于等于)、<(小于)、<=(小于等于),<>(不等于))
多行操作符:右边子查询可以返回多行,但是必须是单列,常见有all、any、in,其中all和any必须与单行比较运算符结合使用
操作符 | 说明 |
---|---|
in | 表示任何一个。栗子:num IN(1,2,3)–>判断num是否在1||2||3值中 |
any | b表示和子查询返回的任意一个值比较。栗子:num>ANY(1,2,3)–>num>1||num>2||num>3 |
all | 表示和子查询返回的所有值比较。栗子:num>ALL(1,2,3)–>num>1&&num>2&&num>3 |
exists | 表示判断子查询是否有返回值(true/false) |
①查询薪资最高的员工和姓名
mysql> SELECT ename FROM t_employee WHERE salary =(SELECT MAX(salary) FROM t_employee);
+--------+
| ename |
+--------+
| 刘化环 |
| 陈龙 |
+--------+
2 rows in set (0.00 sec)
② 查询和林大侠、周积极他俩的部门编号
mysql> SELECT did FROM t_employee WHERE ename IN ('林大侠','周积极');
+------+
| did |
+------+
| 1 |
| 4 |
+------+
2 rows in set (0.00 sec)
③查询其他员工,编号和林大侠、周积他俩一样
mysql> SELECT * FROM t_employee WHERE did
IN (SELECT did FROM t_employee WHERE ename IN ('林大侠','周积极'));
+-----+----------+--------+---------+------------+------------+--------------+------+
| eid | ename | gender | salary | birthday | hiredate | native_place | did |
+-----+----------+--------+---------+------------+------------+--------------+------+
| 1 | 林大侠 | 男 | 8000.46 | 1980-10-08 | 2011-07-28 | 浙江 | 1 |
| 2 | 刘猪猪 | 男 | 7000.67 | 1984-08-03 | 2015-07-03 | 河北 | 1 |
| 3 | 猪猪侠 | 男 | 8000 | 1985-04-09 | 2014-07-01 | 陕西 | 1 |
| 5 | 周泡泡 | 男 | 8567 | 1978-08-02 | 2015-01-01 | 吉林 | 1 |
| 6 | 斯瓦辛格 | 男 | 12000 | 1985-04-03 | 2015-02-02 | 内蒙古 | 1
| 7 | 乐乐 | 男 | 15700 | 1982-08-02 | 2015-03-03 | 新疆 | 1 |
| 8 | 周大龙 | 男 | 9000 | 1983-03-02 | 2015-01-06 | 西藏 | 1 |
| 9 | 李峰 | 男 | 7897 | 1984-09-01 | 2015-04-01 | 天津 | 1 |
| 10 | 韩噶 | 男 | 8789 | 1989-04-02 | 2014-09-03 | 江苏 | 1 |
| 11 | 黄大大 | 男 | 15678 | 1983-05-07 | 2014-04-04 | 安徽 | 1 |
| 12 | 范冰 | 女 | 8909 | 1986-04-02 | 2014-02-08 | 贵州 | 1
| 13 | 李冰 | 女 | 18760 | 1987-04-09 | 2015-06-07 | 四川 | 1 |
| 18 | 凯记卡 | 女 | 16788 | 1978-09-04 | 2013-04-05 | 福建 | 4 |
| 19 | 周积极 | 女 | 7876 | 1988-06-13 | 2014-04-07 | 广西 | 4 |
| 23 | 陈龙 | 男 | 130990 | 1990-02-04 | 2016-05-09 | 上海 | 1 |
+-----+----------+--------+---------+------------+------------+--------------+------+
15 rows in set (0.00 sec)
④查询林大侠、李大象、张章子他们三个薪资
mysql> SELECT salary FROM t_employee WHERE ename IN('林大侠','李大象','张章子');
+---------+
| salary |
+---------+
| 8000.46 |
| 9456 |
| 15099 |
+---------+
3 rows in set (0.00 sec)
⑤查询比林大侠、李大象、张章子他们的薪资都高的员工
mysql> SELECT * FROM t_employee WHERE salary >ALL(SELECT salary FROM t_employee WHERE ename IN('林大侠','李大象','张章子'));
+-----+--------+--------+--------+------------+------------+--------------+------+
| eid | ename | gender | salary | birthday | hiredate | native_place | did |
+-----+--------+--------+--------+------------+------------+--------------+------+
| 7 | 乐乐 | 男 | 15700 | 1982-08-02 | 2015-03-03 | 新疆 | 1 |
| 11 | 黄大大 | 男 | 15678 | 1983-05-07 | 2014-04-04 | 安徽 | 1 |
| 13 | 李冰 | 女 | 18760 | 1987-04-09 | 2015-06-07 | 四川 | 1 |
| 14 | 邻娜 | 女 | 18978 | 1990-01-01 | 2015-09-05 | 成都 | 2 |
| 18 | 凯记卡 | 女 | 16788 | 1978-09-04 | 2013-04-05 | 福建 | 4 |
| 22 | 刘化环 | 男 | 130990 | 1990-11-09 | 2016-08-09 | 北京 | 3 |
| 23 | 陈龙 | 男 | 130990 | 1990-02-04 | 2016-05-09 | 上海 | 1 |
+-----+--------+--------+--------+------------+------------+--------------+------+
7 rows in set (0.00 sec)
(2)from型子查询:即把内层sql语句查询的结果作为临时表供外层sql语句再次查询。
① 查询部门编号、部门的名称、部门的平均工资
mysql> SELECT did,AVG(salary) FROM t_employee GROUP BY did;
+------+--------------------+
| did | AVG(salary) |
+------+--------------------+
| 1 | 19945.471538461537 |
| 2 | 11708.5 |
| 3 | 70223 |
| 4 | 12332 |
| 5 | 11065.5 |
+------+--------------------+
5 rows in set (0.00 sec)
②用子查询的结果当做一张临时表和部门表进行联合查询
给子查询的结果,取别名,当做临时表
给分组函数的计算结果列取别名,当做一个普通的列使用
mysql> SELECT temp.did,dname,temp.pingjun
-> FROM (SELECT did,AVG(salary) AS pingjun FROM t_employee GROUP BY did) AS temp
-> INNER JOIN t_department ON temp.did =t_department.`did`;
+------+--------+--------------------+
| did | dname | pingjun |
+------+--------+--------------------+
| 1 | 开发部 | 19945.471538461537 |
| 2 | 前端部 | 11708.5 |
| 3 | 运维部 | 70223 |
| 4 | 客户部 | 12332 |
| 5 | 测试部 | 11065.5 |
+------+--------+--------------------+
5 rows in set (0.00 sec)
(3)exists型子查询
查询有员工的部门
mysql> SELECT did,dname,description FROM t_department WHERE EXISTS
-> (SELECT * FROM t_employee WHERE t_employee.did=t_department.`did`);
+-----+--------+------------------+
| did | dname | description |
+-----+--------+------------------+
| 1 | 开发部 | 负责后台开发工作 |
| 2 | 前端部 | 负责前端开发工作 |
| 3 | 运维部 | 负责服务运营工作 |
| 4 | 客户部 | 负责需求服务工作 |
| 5 | 测试部 | 负责测试工作 |
+-----+--------+------------------+
5 rows in set (0.00 sec)
☝上述分享来源个人总结,如果分享对您有帮忙,希望您积极转载;如果您有不同的见解,希望您积极留言,让我们一起探讨,您的鼓励将是我前进道路上一份助力,非常感谢!我会不定时更新相关技术动态,同时我也会不断完善自己,提升技术,希望与君同成长同进步!
☞本人博客:https://coding0110lin.blog.csdn.net/ 欢迎转载,一起技术交流吧!