mysql 子查询
子查询(subquery),查询其结果用来作为另一个查询的参数。
单值的子查询
一个子查询如果产生一个单纯的数据,该子查询就如同一个常量,那么就可以像使用常量一样使用它。在实际应用中,我们经常要求子查询只返回一个值,这样就可以将一列值和单个子查询返回值进行比较,这时,可以使用等于(=)、不等于(<>)、大于(>)、小于(<)、大于等于(>=)、小于等于(<=)等运算符。
1 2 | SELECT * FROM user where dept_id = ( select id from dept where dept_name = 'IT' ) |
在子查询中使用聚合函数
1 2 | SELECT * FROM user where salary > ( select avg (salary) from user ) |
比较判式的两边均采用聚合分析的子查询
1 2 | SELECT * FROM user where ( select avg (salary) from user as user2 where user2.dept_id = user .dept_id ) > ( select avg (salary) from user ) |
在SELECT子句中使用子查询
1 2 3 | SELECT *, ( select count (1) from user where ` user `.dept_id = dept.id) as user_count FROM dept |
多行的子查询
一个子查询除了可以产生一个单一值外,也可以产生一个关系,该关系可以包含若干元组。SQL提供了若干对于关系的操作符,并产生一个布尔型的结果,这些操作符主要用在子查询的结果关系上,它主要包括:IN、EXISTS、SOME(ANY)、ALL、UNIQUE等。
采用IN子查询实现集合交运算
当使用IN运算符来引入子查询时,就是告诉DBMS执行子查询集合成员测试,即把源表中的列值与子查询的返回结果进行比较,如果列值包与返回结果集中的列数据值之一相匹配,那么IN判别式求值为True,查询结果就包含这行数据。
1 2 | SELECT * FROM user where id in ( select id from user where dept_id = 1) |
采用IN子查询实现集合差运算
1 2 | SELECT * FROM user where id not in ( select id from user where dept_id = 1) |
EXISTS子查询
在某些情况下,我们只需要子查询返回一个True或者False,子查询数据内容本身并不重要,这时,可使用EXISTS判式来定义子查询。EXISTS判式用来测试集合是否为空,它总是与子查询结合使用,而且只要子查询中至少返回一个值,EXISTS判式的值就为True。如果子查询的结果表中没有值(表中没有行满足子查询的WHERE子句的搜索条件),那么EXISTS判式的值为False。
1 2 3 4 5 | SELECT * FROM user where exists ( select * from dept where id = user .dept_id) SELECT * FROM user where NOT exists ( select * from dept where id = user .dept_id) |
SOME/ALL子查询
只要我们使用了SQL比较运算符(等于=、不等于<>、大于>、小于<、大于等于>=、小于等于<=)中的一个来比较两个表达式的值,那么运算符前后的表达式都必须为单一值。只有当子查询返回值为单值时,才可使用子查询作为比较判式的表达式之一。而数量词SOME、ANY和ALL则允许使用比较运算符将单值与子查询返回的值加以比较,这里的子查询返回的结果可以是多行的。
1 2 | SELECT * FROM user where salary >= ALL ( select avg (salary) from user ) |
UNIQUE子查询
UNIQUE运算符用来测试集合是否存在重复元组。与EXISTS判式相似,它总是与子查询结合使用,而且只要子查询结果中没有重复记录,UNIQUE判式的值就为True;如果子查询的结果表中有重复的记录,那么UNIQUE判式的值为False。
1 2 | SELECT * FROM user where UNIQUE ( select dept_id from dept where id = user .dept_id) × |
myslq没有提供对UNIQUE判式的支持
可以在子查询中采用聚合函数实现上述查询
1 2 | SELECT * FROM user where ( select count (1) from dept where id = user .dept_id) = 1 |
相关子查询
由前面介绍的一些子查询我们不难发现,有些复杂的子查询需要执行若干次,因为每次执行时,都需要来自子查询外部的元组变量的值,也就是说,子查询的执行要依赖于上一层查询元组的当前值,我们将这种子查询称之为相关子查询。前面介绍的EXISTS子查询,基本上全部是相关子查询。
在HAVING子句中使用相关子查询
在SQL中,DBMS使用WHERE子句中的搜索条件来过滤查询结果表中不想要的行,使用HAVING子句中的搜索条件删除那些不想要的。
1 2 | SELECT * FROM user HAVING salary > ( select avg (salary) from user ) |
嵌套子查询
子查询也可以出现在其他子查询中。位于其他子查询内的子查询被称为嵌套的子查询
1 2 | SELECT * FROM user where salary > ( select avg (salary) from user where dept_id in ( select id from user where dept_id = 1) ) |
使用子查询创建视图
使用子查询,根据已有的表或者视图创建出新的视图。
1 2 3 | create view view_user_s as SELECT * FROM user where salary > ( select avg (salary) from user ) |
附:示例sql
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | CREATE TABLE `dept` ( `id` int (11) DEFAULT NULL , `dept_name` varchar (255) DEFAULT NULL ) ; CREATE TABLE ` user ` ( `id` int (11) DEFAULT NULL , `dept_id` int (11) DEFAULT NULL , `user_name` varchar (255) DEFAULT NULL , `salary` int (11) DEFAULT NULL ) ; INSERT INTO `test`.`dept` (`id`, `dept_name`) VALUES ( '1' , 'IT' ); INSERT INTO `test`.`dept` (`id`, `dept_name`) VALUES ( '2' , 'HR' ); INSERT INTO `test`.` user ` (`id`, `dept_id`, `user_name`, `salary`) VALUES ( '1' , '1' , '1a' , '100' ); INSERT INTO `test`.` user ` (`id`, `dept_id`, `user_name`, `salary`) VALUES ( '2' , '1' , '1b' , '401' ); INSERT INTO `test`.` user ` (`id`, `dept_id`, `user_name`, `salary`) VALUES ( '3' , '2' , '2a' , '300' ); INSERT INTO `test`.` user ` (`id`, `dept_id`, `user_name`, `salary`) VALUES ( '4' , '2' , '2b' , '200' ); INSERT INTO `test`.` user ` (`id`, `dept_id`, `user_name`, `salary`) VALUES ( '5' , '3' , '3a' , '500' ); |
参考:SQL查询的艺术-第10章 子查询
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律