SQL语言 - 子查询
SQL语句中嵌套SELECT语句,称谓嵌套查询,又称子查询。
概述
语法:
SELECT * FROM t1 WHERE column1 = ( SELECT column1 FROM t2);
子查询外部的语句可以是 INSERT / UPDATE / DELETE / SELECT 的任何一个
根据子查询结果可以分为:
- 标量子查询(子查询结果为单个值)
- 列子查询(子查询结果为一列)
- 行子查询(子查询结果为一行)
- 表子查询(子查询结果为多行多列)
根据子查询位置可分为:
- WHERE 之后
- FROM 之后
- SELECT 之后
标量子查询
子查询返回的结果是单个值(数字、字符串、日期等)。 常用操作符:- < > > >= < <=
例子:
-- 查询 "销售部" 所有员工信息
select id from dept where name = '销售部';
-- 根据销售部部门ID,查询员工信息
select * from emp where dept_id = 4;
-- 合并(子查询)
select * from emp where dept_id = (select id from dept where name = '销售部');
-- 查询在 "方东白" 入职之后的员工信息
select entrydate from emp where name = '方东白';
-- 根据入职日期查询之后入职的员工信息
select * from emp where entrydate > '2009-02-12';
-- 合并(子查询)
select * from emp where entrydate > (select entrydate from emp where name = '方东白');
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
查询结果:
mysql> select id from dept where name = '销售部';
+----+
| id |
+----+
| 4 |
+----+
1 row in set (0.00 sec)
mysql> select * from emp where dept_id = 4;
+----+-----------+------+--------------+--------+------------+-----------+---------+
| id | name | age | job | salary | entrydate | managerid | dept_id |
+----+-----------+------+--------------+--------+------------+-----------+---------+
| 14 | 张三丰 | 88 | 销售总监 | 14000 | 2004-10-12 | 1 | 4 |
| 15 | 俞莲舟 | 38 | 销售 | 4600 | 2004-10-12 | 14 | 4 |
| 16 | 宋远桥 | 40 | 销售 | 4600 | 2004-10-12 | 14 | 4 |
+----+-----------+------+--------------+--------+------------+-----------+---------+
3 rows in set (0.00 sec)
mysql> select * from emp where dept_id = (select id from dept where name = '销售部');
+----+-----------+------+--------------+--------+------------+-----------+---------+
| id | name | age | job | salary | entrydate | managerid | dept_id |
+----+-----------+------+--------------+--------+------------+-----------+---------+
| 14 | 张三丰 | 88 | 销售总监 | 14000 | 2004-10-12 | 1 | 4 |
| 15 | 俞莲舟 | 38 | 销售 | 4600 | 2004-10-12 | 14 | 4 |
| 16 | 宋远桥 | 40 | 销售 | 4600 | 2004-10-12 | 14 | 4 |
+----+-----------+------+--------------+--------+------------+-----------+---------+
3 rows in set (0.00 sec)
mysql> select entrydate from emp where name = '方东白';
+------------+
| entrydate |
+------------+
| 2009-02-12 |
+------------+
1 row in set (0.00 sec)
mysql> select * from emp where entrydate > '2009-02-12';
+----+-----------+------+--------+--------+------------+-----------+---------+
| id | name | age | job | salary | entrydate | managerid | dept_id |
+----+-----------+------+--------+--------+------------+-----------+---------+
| 9 | 丁敏君 | 23 | 出纳 | 5250 | 2009-05-13 | 7 | 3 |
| 17 | 陈友谅 | 42 | NULL | 2000 | 2011-10-12 | 1 | NULL |
+----+-----------+------+--------+--------+------------+-----------+---------+
2 rows in set (0.01 sec)
mysql> select * from emp where entrydate > (select entrydate from emp where name = '方东白');
+----+-----------+------+--------+--------+------------+-----------+---------+
| id | name | age | job | salary | entrydate | managerid | dept_id |
+----+-----------+------+--------+--------+------------+-----------+---------+
| 9 | 丁敏君 | 23 | 出纳 | 5250 | 2009-05-13 | 7 | 3 |
| 17 | 陈友谅 | 42 | NULL | 2000 | 2011-10-12 | 1 | NULL |
+----+-----------+------+--------+--------+------------+-----------+---------+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
列子查询
子查询返回的结果是一列(可以是多行),这种子查询称为列子查询。
常用操作符:
操作符 | 描述 |
---|---|
IN | 在指定的集合范围内,多选一 |
NOT IN | 不在指定的集合范围内 |
ANY | 子查询返回列表中,有任意一个满足即可 |
SOME | 与ANY等同,使用SOME的地方都可以使用ANY |
ALL | 子查询返回列表的所有值都必须满足 |
例子:
-- 查询销售部和市场部的所有员工信息
select * from emp where dept_id in (select id from dept where name = '销售部' or name = '市场部');
-- 查询比财务部所有人工资都高的员工信息
select * from emp where salary > all ( select salary from emp where dept_id = (select id from dept where name = '财务部'));
-- 查询比研发部任意一人工资高的员工信息
select * from emp where salary > any ( select salary from emp where dept_id = (select id from dept where name = '研发部') );
1
2
3
4
5
6
2
3
4
5
6
查询结果:
mysql> select * from emp where dept_id in (select id from dept where name = '销售部' or name = ' 市场部');
+----+-----------+------+-----------------+--------+------------+-----------+---------+
| id | name | age | job | salary | entrydate | managerid | dept_id |
+----+-----------+------+-----------------+--------+------------+-----------+---------+
| 10 | 赵敏 | 20 | 市场部总监 | 12500 | 2004-10-12 | 1 | 2 |
| 11 | 鹿杖客 | 56 | 职员 | 3750 | 2006-10-03 | 10 | 2 |
| 12 | 鹤笔翁 | 19 | 职员 | 3750 | 2007-05-09 | 10 | 2 |
| 13 | 方东白 | 19 | 职员 | 5500 | 2009-02-12 | 10 | 2 |
| 14 | 张三丰 | 88 | 销售总监 | 14000 | 2004-10-12 | 1 | 4 |
| 15 | 俞莲舟 | 38 | 销售 | 4600 | 2004-10-12 | 14 | 4 |
| 16 | 宋远桥 | 40 | 销售 | 4600 | 2004-10-12 | 14 | 4 |
+----+-----------+------+-----------------+--------+------------+-----------+---------+
7 rows in set (0.00 sec)
mysql>
mysql> select * from emp where salary > all ( select salary from emp where dept_id = (select id from dept where name = '财务部'));
Empty set (0.00 sec)
mysql> select * from emp where salary > any ( select salary from emp where dept_id = (select id from dept where name = '研发部') );
+----+-----------+------+-----------------+--------+------------+-----------+---------+
| id | name | age | job | salary | entrydate | managerid | dept_id |
+----+-----------+------+-----------------+--------+------------+-----------+---------+
| 1 | 金庸 | 66 | 总裁 | 20000 | 2000-01-01 | NULL | 5 |
| 2 | 张无忌 | 20 | 项目经理 | 12500 | 2005-12-05 | 1 | 1 |
| 3 | 杨逍 | 33 | 开发 | 8400 | 2000-11-03 | 2 | 1 |
| 4 | 韦一笑 | 48 | 开发 | 11000 | 2002-02-05 | 2 | 1 |
| 5 | 常遇春 | 43 | 开发 | 10500 | 2004-09-07 | 3 | 1 |
| 7 | 灭绝 | 60 | 财务总监 | 8500 | 2002-09-12 | 1 | 3 |
| 8 | 周芷若 | 19 | 会计 | 48000 | 2006-06-02 | 7 | 3 |
| 10 | 赵敏 | 20 | 市场部总监 | 12500 | 2004-10-12 | 1 | 2 |
| 14 | 张三丰 | 88 | 销售总监 | 14000 | 2004-10-12 | 1 | 4 |
+----+-----------+------+-----------------+--------+------------+-----------+---------+
9 rows in set (0.00 sec)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
行子查询
子查询返回的结果是一行(可以是多列),这种子查询称为行子查询。
常用操作符:=, <, >, IN, NOT IN
例子:
-- 查询与 "张无忌" 的薪资及直属领导相同的员工信息 ;
select * from emp where (salary,managerid) = (select salary, managerid from emp where name = '张无忌');
1
2
2
查询结果:
mysql> select * from emp where (salary,managerid) = (select salary, managerid from emp where name = '张无忌');
+----+-----------+------+-----------------+--------+------------+-----------+---------+
| id | name | age | job | salary | entrydate | managerid | dept_id |
+----+-----------+------+-----------------+--------+------------+-----------+---------+
| 2 | 张无忌 | 20 | 项目经理 | 12500 | 2005-12-05 | 1 | 1 |
| 10 | 赵敏 | 20 | 市场部总监 | 12500 | 2004-10-12 | 1 | 2 |
+----+-----------+------+-----------------+--------+------------+-----------+---------+
1
2
3
4
5
6
2
3
4
5
6
表子查询
返回的结果是多行多列 常用操作符:IN
例子:
-- 查询与 "鹿杖客" , "宋远桥" 的职位和薪资相同的员工信息
select * from emp where (job,salary) in ( select job, salary from emp where name = '鹿杖客' or name = '宋远桥' );
-- 查询入职日期是 "2006-01-01" 之后的员工信息 , 及其部门信息
select e.*, d.* from (select * from emp where entrydate > '2006-01-01') e left join dept d on e.dept_id = d.id ;
1
2
3
4
2
3
4
查询结果:
mysql> select * from emp where (job,salary) in ( select job, salary from emp where name = '鹿杖客' or name = '宋远桥' );
+----+-----------+------+--------+--------+------------+-----------+---------+
| id | name | age | job | salary | entrydate | managerid | dept_id |
+----+-----------+------+--------+--------+------------+-----------+---------+
| 11 | 鹿杖客 | 56 | 职员 | 3750 | 2006-10-03 | 10 | 2 |
| 12 | 鹤笔翁 | 19 | 职员 | 3750 | 2007-05-09 | 10 | 2 |
| 15 | 俞莲舟 | 38 | 销售 | 4600 | 2004-10-12 | 14 | 4 |
| 16 | 宋远桥 | 40 | 销售 | 4600 | 2004-10-12 | 14 | 4 |
+----+-----------+------+--------+--------+------------+-----------+---------+
4 rows in set (0.00 sec)
mysql> select e.*, d.* from (select * from emp where entrydate > '2006-01-01') e left join dept d on e.dept_id = d.id ;
+----+-----------+------+--------+--------+------------+-----------+---------+------+-----------+
| id | name | age | job | salary | entrydate | managerid | dept_id | id | name |
+----+-----------+------+--------+--------+------------+-----------+---------+------+-----------+
| 8 | 周芷若 | 19 | 会计 | 48000 | 2006-06-02 | 7 | 3 | 3 | 财务部 |
| 9 | 丁敏君 | 23 | 出纳 | 5250 | 2009-05-13 | 7 | 3 | 3 | 财务部 |
| 11 | 鹿杖客 | 56 | 职员 | 3750 | 2006-10-03 | 10 | 2 | 2 | 市场部 |
| 12 | 鹤笔翁 | 19 | 职员 | 3750 | 2007-05-09 | 10 | 2 | 2 | 市场部 |
| 13 | 方东白 | 19 | 职员 | 5500 | 2009-02-12 | 10 | 2 | 2 | 市场部 |
| 17 | 陈友谅 | 42 | NULL | 2000 | 2011-10-12 | 1 | NULL | NULL | NULL |
+----+-----------+------+--------+--------+------------+-----------+---------+------+-----------+
6 rows in set (0.01 sec)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23