Mysql 四: 数据库复杂的查询

存储关系

现在有学生表、科目表这两张表,我需要再创建一张成绩表,用来表示学生各科目的成绩,

如下 :

一个学生可以有多个成绩,一个成绩只能属于某个学生,一个 科目 可以有多个成绩,一个成绩只能属于某个科目。

把外键 存到 1 对 n 中的 n 里面去。

即 : 一对多的情况下,在 多 的那张表里面创建一个外键指向 一 的那张表 的 id,

多对多的 情况下需要创建第三张表用来存储这两种表的id作为外键以及这两张表的关系,就比如这里

的 学生 与 成绩。

如下创建成绩表。

create table scores(id int auto_increment primary key,

stuid int,

subid int,

score decimal(5,2),

foreign key(stuid) references students(id),

foreign key(subid) references subjects(id));

比如我需要插入一条数据,学号 为 1 的 学生 的 id 为1的科目 考了 100分

insert into scores value(0,1,1,100);

为什么我执行

insert into scores value(0,10,10,100);

不报错??

外键的级联操作

在删除 student表的数据时,如果这个 id 值在 scores 中已经存在,则会抛出异常

推荐使用逻辑删除,还可以解决这个问题

可以创建表时指定级联操作,也可以在创建表后再修改外键的级联操作

语法 :

alert table scores add constraint stu_sco foreign key(stuid) references student

级联操作的类型包括 :

restrict(限制) : 默认值,抛出异常

cascade(级联) : 如果主表 的记录被删除,则从表中相关联的记录都会被删掉

set null : 将外键设置为空

no action : 什么都不做

连接查询

比如我现在要看所有学生的成绩,需要显示

名字 科目 成绩

students.name subjecys.stitle scores.score

而我只查成绩表给出的是 id ,而 id 对应的表在另外一张表里面,这样就需要进行连接查询。

如下 :

select students.name,subjects.stitle,scores.score

from scores

inner join students on scores.stuid=students.id

inner join subjects on scores.subid=subjects.id;

或者 :

select students.name,subjects.stitle,scores.score

from students

inner join scores on scores.stuid=students.id

inner join subjects on scores.subid=subjects.id;

结果 :

+--------+--------+-------+

| name | stitle | score |

+--------+--------+-------+

| 郭靖 | python | 99.00 |

+--------+--------+-------+

1 row in set (0.00 sec)

1.当你的结果集来源于多张表的时候就要考虑连接查询 。

2.先找到这些表的关系 ,如例 : 科目 和学生没有直接关系,学生 和成绩有直接 关系,

科目和成绩也有直接 关系,由此所有 的 关系都建立起来 了。

3.构造 sql 语句, 注意语法的 join 和 on 关键字 。

语法 :

select 表名1.字段1 , 表名2.字段3 ,表名2.字段3,..

from 表名1(作为基础的表)

inner join 表名2 on 表名1.外键2=表名2.id

inner join 表名3 on 表名1.外键3=表名3.id;

其中 from 随便先写 哪张表无所谓,但是 on 后面的条件一定不能错。

join 左边的表 称为 左表, join 右边的表 称为 右表 。

还有一点 要注意 , to 后面的表,一定要先在 to 前面出现过,否则会报错,如下

select students.name,subjects.stitle,scores.score

from students

inner join subjects on scores.stuid=students.id

inner join scores on scores.subid=subjects.id;

ERROR 1054 (42S22): Unknown column 'scores.stuid' in 'on clause'

连接查询分为三种 :

一、表A inner join 表B (内连接): 表A与表B匹配的行会出现在结果集中。

二、表A left join 表B (左连接):表A与表B匹配的行会出现在结果集中,外加表A中独有的数据,

未对应的数据使用 null 填充。

mysql> select * from scores right join students on scores.stuid=students.id;

+------+-------+-------+-------+----+-----------+--------+---------------------+----------+-----------+

| id | stuid | subid | score | id | name | gender | brithday | isDelete | hometwon |

+------+-------+-------+-------+----+-----------+--------+---------------------+----------+-----------+

| 6 | 7 | 1 | 99.00 | 7 | 郭靖 | | 0000-00-00 00:00:00 | | 蒙古 |

| 7 | 7 | 10 | 99.00 | 7 | 郭靖 | | 0000-00-00 00:00:00 | | 蒙古 |

| NULL | NULL | NULL | NULL | 2 | 黄蓉 | | 1994-02-14 00:00:00 | | 桃花岛 |

| NULL | NULL | NULL | NULL | 3 | 杨过 | | 1994-02-14 00:00:00 | | NULL |

| NULL | NULL | NULL | NULL | 4 | 小龙女 | | 1994-02-14 00:00:00 | | NULL |

| NULL | NULL | NULL | NULL | 5 | 雕 | | 1994-02-14 00:00:00 | | NULL |

+------+-------+-------+-------+----+-----------+--------+---------------------+----------+-----------+

6 rows in set (0.00 sec)

mysql> select * from scores left join students on scores.stuid=students.id;

+----+-------+-------+-------+------+--------+--------+---------------------+----------+----------+

| id | stuid | subid | score | id | name | gender | brithday | isDelete | hometwon |

+----+-------+-------+-------+------+--------+--------+---------------------+----------+----------+

| 6 | 7 | 1 | 99.00 | 7 | 郭靖 | | 0000-00-00 00:00:00 | | 蒙古 |

| 7 | 7 | 10 | 99.00 | 7 | 郭靖 | | 0000-00-00 00:00:00 | | 蒙古 |

+----+-------+-------+-------+------+--------+--------+---------------------+----------+----------+

2 rows in set (0.00 sec)

------------------------------

左连接时数据的条数 以 join 左边的表为准,字段则是左边的表和右边的表合起来的字段拼接而成。

而左表中某些数据在右表中没有出现则用 null 对应, 这样结果集就是 由这两张表合成 的表。

-----------------------------

三、表A right join 表B (右连接):表A与表B匹配的行会出现在结果集中,外加表B中独有的数据,

未对应的数据使用 null 填充。

-----------------------

右连接跟左连接相反

-----------------------

查询每个学生的平均成绩 :

mysql> select name,avg(score) from scores inner join students on scores.stuid=students.id group by stuid;

+--------+------------+

| name | avg(score) |

+--------+------------+

| 郭靖 | 99.000000 |

+--------+------------+

1 row in set (0.03 sec)

mysql> select * from scores inner join students on scores.stuid=students.id group by stuid;

+----+-------+-------+-------+----+--------+--------+---------------------+----------+----------+

| id | stuid | subid | score | id | name | gender | brithday | isDelete | hometwon |

+----+-------+-------+-------+----+--------+--------+---------------------+----------+----------+

| 6 | 7 | 1 | 99.00 | 7 | 郭靖 | | 0000-00-00 00:00:00 | | 蒙古 |

+----+-------+-------+-------+----+--------+--------+---------------------+----------+----------+

1 row in set (0.00 sec

思路 : 先通过连接查询得到一张大表,里面包含有成绩的学生的学生信息 和成绩信息,

再在这个结果集里面筛选需要的字段 。

select distinct 列/*

from 表1 inner/left/right join 表2 on 表1与表2的关系

where ...

group by ... having ...

order by ... asc/desc

limit sart,count;

猜你喜欢

转载自blog.csdn.net/qq_26128879/article/details/82595025