嵌套在其他查询中的查询。
select student_id
from course_selection
where course_id in
(
select course_id
from courses
where course_teacher='zhang'
);
即首先从课程设置表’courses’中查询出张老师带的所有课的course_id,然后从学生信息表查询选这门课的所有学生。
输出为:
+------------+
| student_id |
+------------+
| 10 |
| 12 |
| 23 |
| 24 |
| 27 |
| 30 |
| 34 |
| 43 |
| 53 |
| 62 |
| 75 |
| 92 |
| 96 |
| 99 |
| 104 |
| 109 |
| 111 |
| 121 |
| 137 |
| 146 |
| 153 |
| 165 |
| 169 |
| 177 |
| 200 |
| 201 |
| 201 |
| 207 |
| 210 |
......
如果需要进一步查询学生信息,那么可以再套一层子查询:
select name,sex,age
from students
where id in
(
select student_id
from course_selection
where course_id in
(
select course_id
from courses
where course_teacher='zhang'
)
);
数出为:
+----------+--------+-----+
| name | sex | age |
+----------+--------+-----+
| ulztnhta | male | 28 |
| dtpndvay | female | 74 |
| ovqjyzwg | male | 92 |
| ybxhrwoz | male | 34 |
| jadwgffz | male | 16 |
| waujztek | male | 68 |
| bbakyjna | male | 72 |
| eefugffs | male | 41 |
| pkgbauyw | male | 28 |
| hhabcnev | female | 29 |
| rnilmphq | female | 23 |
| yqjnalbt | male | 98 |
| ytupftsi | male | 56 |
| iwgravri | female | 66 |
| czbijhwt | female | 94 |
| ivspjvjw | female | 60 |
......
注意事项:
1. 作为子查询的select语句只能检索单列
2. 子查询的性能很底,更有效的方法是使用join语句
例子:
select name,sex,age,
(
select count(*)
from course_selection
where student_id = id
) as courses_total
from students;
可以看到使用一条子查询作为计算字段,查询到的结果为:
+----------+--------+-----+---------------+
| name | sex | age | courses_total |
+----------+--------+-----+---------------+
| tkzpwxdq | male | 15 | 3 |
| brtqrcko | female | 84 | 3 |
| jyjxycgw | male | 44 | 3 |
| iwgnesmt | female | 41 | 3 |
| rnjpfpim | male | 51 | 3 |
| audrwvfz | female | 15 | 3 |
| kvyevrae | male | 91 | 3 |
| zjqknchl | male | 92 | 3 |
| vrotlokt | male | 43 | 3 |
| jklszqyz | female | 12 | 3 |
......
同时发现这种方式的查询是非常慢的。
关系表的存在是为了降低数据的冗余度和增强数据库的可伸缩性。
例如本文使用的数据中,在存储选课信息时,没有把每一项选课记录的学生和课程信息都列在选课情况表中,而是建立了另外两张表——学生信息表和课程信息表,用来分别存储学生和课程的信息,选课情况表中仅存储学生和课程的id。
这样设计,如果课程信息变动,比如更换了任课老师,只需要改动课程信息表的相应项即可,无需对其他表进行改动,增强了数据库应对改变的能力。
联结的作用是联结几张具有一定关系的表,以便使用一条select语句检索出需要的数据。
联结的创建十分简单:
select id, name, age, course_id
from students, course_selection
where student_id = id;
上面的语句将students和course_selection两张表通过id联结在一起:
+----+----------+-----+-----------+
| id | name | age | course_id |
+----+----------+-----+-----------+
| 0 | tkzpwxdq | 15 | 0 |
| 0 | tkzpwxdq | 15 | 20 |
| 0 | tkzpwxdq | 15 | 48 |
| 1 | brtqrcko | 84 | 0 |
| 1 | brtqrcko | 84 | 11 |
| 1 | brtqrcko | 84 | 48 |
| 2 | jyjxycgw | 44 | 0 |
| 2 | jyjxycgw | 44 | 16 |
| 2 | jyjxycgw | 44 | 34 |
| 3 | iwgnesmt | 41 | 0 |
......
注意where字句的使用,它限定了两张表的行的配对条件,若没有此语句,那么联结表将返回两张表的笛卡尔积,即第一张表的一行将与第二章表的每一行进行配对。
上面使用的联结称为等值联结,又叫内部联结,它基于两张表间的相等测试,可以使用这样的语法:
select id, name, age, course_id
from students inner join course_selection
on student_id = id;
这与上面的语句完全等价。
join语句对联结表的数目没有限制,基本规则也相同:首先指定需要联结的表,然后定义表之间的联系。
这里使用一条join语句完成之前使用嵌套子查询语句实现的功能:查询所有选张老师课的学生信息。
SELECT name, age, sex
FROM students, courses, course_selection
WHERE course_selection.student_id = students.id
AND course_teacher = 'zhang'
AND courses.course_id = course_selection.course_id;
输出:
+----------+-----+--------+
| name | age | sex |
+----------+-----+--------+
| ulztnhta | 28 | male |
| dtpndvay | 74 | female |
| ovqjyzwg | 92 | male |
| ybxhrwoz | 34 | male |
| jadwgffz | 16 | male |
| waujztek | 68 | male |
| bbakyjna | 72 | male |
| eefugffs | 41 | male |
| pkgbauyw | 28 | male |
| hhabcnev | 29 | female |
| rnilmphq | 23 | female |
| yqjnalbt | 98 | male |
| ytupftsi | 56 | male |
......
同嵌套子查询的输出一模一样。