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章 子查询

 

posted @   草木物语  阅读(282)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示