第8天-sql子查询和联结表

一、子查询

嵌套在其他查询中的查询。

1、 利用子查询进行过滤

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语句

2、作为计算字段使用子查询

例子:

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 |
......

同时发现这种方式的查询是非常慢的。

二、联结表

1、关系表

关系表的存在是为了降低数据的冗余度和增强数据库的可伸缩性。

例如本文使用的数据中,在存储选课信息时,没有把每一项选课记录的学生和课程信息都列在选课情况表中,而是建立了另外两张表——学生信息表和课程信息表,用来分别存储学生和课程的信息,选课情况表中仅存储学生和课程的id。

这样设计,如果课程信息变动,比如更换了任课老师,只需要改动课程信息表的相应项即可,无需对其他表进行改动,增强了数据库应对改变的能力。

2、联结

2.1 创建联结

联结的作用是联结几张具有一定关系的表,以便使用一条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字句的使用,它限定了两张表的行的配对条件,若没有此语句,那么联结表将返回两张表的笛卡尔积,即第一张表的一行将与第二章表的每一行进行配对。

2.2 内部联结

上面使用的联结称为等值联结,又叫内部联结,它基于两张表间的相等测试,可以使用这样的语法:

select id, name, age, course_id
from students inner join course_selection
on student_id = id;

这与上面的语句完全等价。

2.3 联结多个表

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   |
......

同嵌套子查询的输出一模一样。

你可能感兴趣的:(sql)