1、什么是子查询? 子查询是将一个查询语句嵌套在另一个查询语句中。内层查询语句的查询结果,可以作为外层查询语句提供条件。
2、引发子查询的情况?
使用[NOT]IN的子查询
使用比较运算符的子查询(=、>、 <、>=、 <=、 <>、 !=、 <=>)
使用[NOT]EXISTS的子查询
使用ANY|SOME或者ALL的子查询
运算符
ANY
SOME
ALL
>、>=
最小值
最小值
最大值
<、<=
最大值
最大值
最小值
=
任意值
任意值
<>、!=
任意值
使用[NOT] IN
的子查询 首先重置一下employee
和department
表:
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 mysql> DROP TABLE employee,department; Query OK, 0 rows affected (0.01 sec) mysql> CREATE TABLE IF NOT EXISTS department( -> id TINYINT UNSIGNED AUTO_INCREMENT KEY, -> depName VARCHAR(20) NOT NULL UNIQUE -> )ENGINE=INNODB; Query OK, 0 rows affected (0.03 sec) mysql> INSERT department(depName) VALUES('教学部'), -> ('市场部'), -> ('运营部'), -> ('督导部'); Query OK, 4 rows affected (0.00 sec) Records: 4 Duplicates: 0 Warnings: 0 mysql> CREATE TABLE IF NOT EXISTS employee( -> id SMALLINT UNSIGNED AUTO_INCREMENT KEY, -> username VARCHAR(20) NOT NULL UNIQUE, -> depId TINYINT UNSIGNED -> )ENGINE=INNODB; Query OK, 0 rows affected (0.01 sec) mysql> INSERT employee(username,depId) VALUES('king',1), -> ('queen',2), -> ('张三',3), -> ('李四',4), -> ('王五',1); Query OK, 5 rows affected (0.00 sec) Records: 5 Duplicates: 0 Warnings: 0
例如我们想查看部门下面的员工,会分别执行以下命令:
1 2 SELECT * FROM department;SELECT id ,username FROM employee WHERE depId IN (1 ,2 ,3 ,4 );
通过第一个语句查询到部门的depId
然后用IN
来查询,而现在我们可以将两条语句整合成一条语句,查询结果是一样的,同样的NOT IN
也是一样的:
1 SELECT id ,username FROM employee WHERE depId IN (SELECT id FROM department);
使用比较运算符的子查询 创建学员表student
和奖学金表scholarship
表插入几条测试数据:
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 mysql> # 创建学员表student mysql> CREATE TABLE IF NOT EXISTS student( -> id TINYINT UNSIGNED AUTO_INCREMENT KEY, -> username VARCHAR(20) NOT NULL UNIQUE, -> score TINYINT UNSIGNED -> ); Query OK, 0 rows affected (0.01 sec) mysql> INSERT student(username,score) VALUES('king',95), -> ('king1',35), -> ('king2',45), -> ('king3',55), -> ('king4',65), -> ('king5',75), -> ('king6',80), -> ('king7',90), -> ('king8',25); Query OK, 9 rows affected (0.00 sec) Records: 9 Duplicates: 0 Warnings: 0 mysql> mysql> # 创建奖学金scholarship mysql> CREATE TABLE IF NOT EXISTS scholarship( -> id TINYINT UNSIGNED AUTO_INCREMENT KEY, -> level TINYINT UNSIGNED -> ); Query OK, 0 rows affected (0.01 sec) mysql> INSERT scholarship(level) VALUES(90),(80),(70); Query OK, 3 rows affected (0.00 sec) Records: 3 Duplicates: 0 Warnings: 0
假如我们查询获得一等奖学金的同学,之前我们会这样写:
1 2 SELECT level FROM scholarship WHERE id =1 ;SELECT id ,username FROM student WHERE score>=90 ;
而用了我们的子查询后将两条语句合并在一起:
1 2 3 4 5 6 7 8 mysql> SELECT id,username FROM student WHERE score>=(SELECT level FROM scholarship WHERE id=1); + | id | username | + | 1 | king | | 8 | king7 | + 2 rows in set (0.01 sec)
将子查询放在了括号内,一定是由内向外执行,将子查询的结果当做条件进行查询。
使用[NOT]EXISTS的子查询 [NOT]EXISTS引发子查询是真假条件,如果子查询是假,那么他的外层条件也不会执行,例如我们只有4个部分,那我们查询第五个部门中的员工的话肯定是没有的:
1 SELECT * FROM department WHERE id =5 ;
当然,都没有第五个部门就没有必要查询员工,而用EXISTS
的查询可以这么写:
1 2 mysql> SELECT id,username FROM employee WHERE EXISTS(SELECT * FROM department WHERE id=5); Empty set (0.00 sec)
使用ANY|SOME或者ALL的子查询 例如我们查询所有获得奖学金的学员,首先查一下奖学金:
1 2 3 4 5 6 7 8 9 mysql> SELECT * FROM scholarship; + | id | level | + | 1 | 90 | | 2 | 80 | | 3 | 70 | + 3 rows in set (0.00 sec)
可以看到分数只有大于等于70才能获得奖学金,那么我们利用ANY
或者SOME
可以查到其中的最小值:
1 2 3 4 5 6 7 8 9 10 mysql> SELECT id,username,score FROM student WHERE score>=ANY(SELECT level FROM scholarship); + | id | username | score | + | 1 | king | 95 | | 6 | king5 | 75 | | 7 | king6 | 80 | | 8 | king7 | 90 | + 4 rows in set (0.00 sec)
而ALL
代表大于里面的最大值,例如查询获得一等奖学金的学员:
1 2 3 4 5 6 7 8 mysql> SELECT id,username,score FROM student WHERE score >=ALL(SELECT level FROM scholarship); + | id | username | score | + | 1 | king | 95 | | 8 | king7 | 90 | + 2 rows in set (0.00 sec)
而<=
是一样的效果,=
和!=
就相当于IN
和NOT IN
:
1 2 3 4 5 6 7 8 mysql> SELECT id,username,score FROM student WHERE score=ANY(SELECT level FROM scholarship); + | id | username | score | + | 7 | king6 | 80 | | 8 | king7 | 90 | + 2 rows in set (0.01 sec)
3、将查询结果写入到数据表 1 2 INSERT [INTO ] tbl_name [(col_name,...)]SELECT ...
这个语句是将查询结果插入到另一张表(执行顺序是先查询后插入),我们创建一个测试表将奖学金结果插入:
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 mysql> CREATE TABLE test1 ( -> id TINYINT UNSIGNED AUTO_INCREMENT KEY, -> num TINYINT UNSIGNED -> ); Query OK, 0 rows affected (0.03 sec) mysql> INSERT test1(id,num) -> SELECT id,score FROM student; Query OK, 9 rows affected (0.01 sec) Records: 9 Duplicates: 0 Warnings: 0 mysql> SELECT * FROM test1; + | id | num | + | 1 | 95 | | 2 | 35 | | 3 | 45 | | 4 | 55 | | 5 | 65 | | 6 | 75 | | 7 | 80 | | 8 | 90 | | 9 | 25 | + 9 rows in set (0.00 sec)
4、创建数据表同时将查询结果写入到数据表 1 2 3 CREATE TABLE [IF NOT EXISTS ] tbl_name[(create_definition,...)] select_statement
这种方式是在建表的时候直接将查询结果插入到表中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 mysql> CREATE TABLE test2 ( -> id TINYINT UNSIGNED AUTO_INCREMENT KEY, -> score TINYINT UNSIGNED -> )SELECT id,score FROM student; Query OK, 9 rows affected (0.02 sec) Records: 9 Duplicates: 0 Warnings: 0 mysql> SELECT * FROM test2; + | id | score | + | 1 | 95 | | 2 | 35 | | 3 | 45 | | 4 | 55 | | 5 | 65 | | 6 | 75 | | 7 | 80 | | 8 | 90 | | 9 | 25 | + 9 rows in set (0.01 sec)