Skip to content
On this page

子查询

多表查询,多个表查询语句

标量子查询

sql
mysql> select * from student_score where number=(select number from student_info where name="杜琦燕");
+----------+-----------------------------+-------+
| number   | subject                     | score |
+----------+-----------------------------+-------+
| 20180102 | 母猪的产后护理              |   100 |
| 20180102 | 论萨达姆的战争准备          |    98 |
+----------+-----------------------------+-------+
2 rows in set (0.00 sec)

mysql>
  • () 保住的语句就是子查询或者说是内层查询,外面的叫外层查询;
  • 在一个查询语句中需要用到更多的表的话,那么在一个子查询中可以继续嵌套另一个子查询
  • 在执行查询语句时,将按照从内到外的顺序依次执行这些查询
  • 子查询结果只有一个值,叫标量子查询

可以使用类名

sql
mysql> select (select number from student_info where name="范剑") as "学号";
+----------+
| 学号     |
+----------+
| 20180105 |
+----------+
1 row in set (0.00 sec)

mysql>

也可以使用表达式;学号大于杜琦燕的学生成绩

sql
mysql> select * from student_score where number > (select number from student_info where name="杜琦燕");
+----------+-----------------------------+-------+
| number   | subject                     | score |
+----------+-----------------------------+-------+
| 20180103 | 母猪的产后护理              |    59 |
| 20180103 | 论萨达姆的战争准备          |    61 |
| 20180104 | 母猪的产后护理              |    55 |
| 20180104 | 论萨达姆的战争准备          |    46 |
+----------+-----------------------------+-------+
4 rows in set (0.00 sec)

mysql>

列子查询

查询计算机工程专业的学生成绩,需要从 stundent_info 表中查询到学生 number,再在 student_score表中查询中成绩

sql
mysql> select * from student_score where number in (select number from student_info where  major like "计算机%");
+----------+-----------------------------+-------+
| number   | subject                     | score |
+----------+-----------------------------+-------+
| 20180101 | 母猪的产后护理              |    78 |
| 20180101 | 论萨达姆的战争准备          |    88 |
| 20180102 | 母猪的产后护理              |   100 |
| 20180102 | 论萨达姆的战争准备          |    98 |
+----------+-----------------------------+-------+
4 rows in set (0.00 sec)

mysql>

子查询结果集包含多个列结果,这个叫做列子查询,使用 in 操作符匹配列表

行子查询

只要子查询的结果集中最多只包含一条记录,而且这条记录中有超过一个列的数据(如果该条记录只包含一个列的话,该子查询就成了标量子查询),那么这个子查询就可以被称之为行子查询

sql
mysql> select * from student_score where (number, subject)=(select number, "母猪的产后护理" from student_info limit 1);
+----------+-----------------------+-------+
| number   | subject               | score |
+----------+-----------------------+-------+
| 20180104 | 母猪的产后护理        |    55 |
+----------+-----------------------+-------+
1 row in set (2.32 sec)

mysql>

表子查询

如果子查询结果集中包含多行多列,那么这个子查询也可以被称之为表子查询

sql
mysql> select * from student_score where (number, subject) in (select number, "母猪的产后护理" from student_info where major like "计算机%");
+----------+-----------------------+-------+
| number   | subject               | score |
+----------+-----------------------+-------+
| 20180101 | 母猪的产后护理        |    78 |
| 20180102 | 母猪的产后护理        |   100 |
+----------+-----------------------+-------+
2 rows in set (0.00 sec)

mysql>

EXISTS 和 NOT EXISTS 查询

有时候外层查询并不关心子查询中的结果是什么,而只关心子查询的结果集是不是为空集,这时可以用到下边这两个操作符:

操作符示例描述
EXISTSEXISTS (SELECT ...)当子查询结果集不是空集时表达式为真
NOT EXISTSNOT EXISTS (SELECT ...)当子查询结果集是空集时表达式为真
sql
mysql> select * from student_score where exists (select * from student_info where number="2018659");
Empty set (0.00 sec)

mysql>

子查询查询不到,所以外查询是不用再次去查询了,直接返回空

不相关和相关子查询

上面的子查询都可以单独执行,和外层查询没有关联,这种叫做不相关子查询;而有时候子查询中用到了外查询的值,这种就不能单独执行的语句,就是相关子查询。

查询学生的基本信息,但是必须是在 student_score 表中存在成绩的

sql
mysql> select number, name, major from student_info where exists (select number from student_score where student_score.number = student_info.number);
+----------+-----------+--------------------------+
| number   | name      | major                    |
+----------+-----------+--------------------------+
| 20180101 | 杜子腾    | 计算机科学与工程         |
| 20180102 | 杜琦燕    | 计算机科学与工程         |
| 20180103 | 范统      | 软件工程                 |
| 20180104 | 史珍香    | 软件工程                 |
+----------+-----------+--------------------------+
4 rows in set (0.00 sec)

mysql>

对同一个表的子查询

student_score表的母猪的产后护理这门课的成绩中,有哪些超过了平均分的记录

sql
mysql> select * from student_score where subject  like "%护理" and score > avg(score);
ERROR 1111 (HY000): Invalid use of group function
mysql>

我们可以看到报错了~因为聚集函数是用来对分组做数据统计的(如果没有 GROUP BY 语句那么意味着只有一个分组),而 WHERE 子句是以记录为单位来执行过滤操作的,在 WHERE 子句执行完成之后才会得到分组,也就是说:聚集函数不能放到WHERE子句中!!!

sql
mysql> select * from student_score where subject like "%护理%" and score > (select avg(score) from student_score where subject like "%护理");
+----------+-----------------------+-------+
| number   | subject               | score |
+----------+-----------------------+-------+
| 20180101 | 母猪的产后护理        |    78 |
| 20180102 | 母猪的产后护理        |   100 |
+----------+-----------------------+-------+
2 rows in set (0.00 sec)

mysql>

我们使用子查询先统计出了母猪的产后护理这门课的平均分,然后再到外层查询中使用这个平均分组成的表达式来作为搜索条件去查找大于平均分的记录。