MySQL练习

假装没事ソ 提交于 2019-12-01 19:42:04

一、表关系

二、创建数据库和表

(一)创建数据库

创建数据库test2,用于存放上述表

mysql> create database test2 default charset utf8 collate utf8_general_ci;
Query OK, 1 row affected (0.00 sec)

(二)创建表

创建上述表以及相应的约束

  • 创建班级表
mysql> create table class (
    ->  cid int primary key auto_increment comment '主键ID' ,
    ->  caption varchar(64) not null comment '班级名称'
    -> )charset=utf8 collate=utf8_general_ci engine=innodb comment='班级表
Query OK, 0 rows affected (0.02 sec)

mysql> show tables;
+-----------------+
| Tables_in_test2 |
+-----------------+
| class           |
+-----------------+
1 row in set (0.00 sec)

mysql> desc class;
+---------+-------------+------+-----+---------+----------------+
| Field   | Type        | Null | Key | Default | Extra          |
+---------+-------------+------+-----+---------+----------------+
| cid     | int(11)     | NO   | PRI | NULL    | auto_increment |
| caption | varchar(64) | NO   |     | NULL    |                |
+---------+-------------+------+-----+---------+----------------+
2 rows in set (0.01 sec)
  • 创建学生表
mysql>   create table student(
    ->   sid int primary key auto_increment comment '主键ID',
    ->   sname varchar(32) not null comment '学生名字',
    ->   gender enum('男','女') not null default '男' comment '性别',
    ->   class_id int comment '关联班级外键',
    ->  constraint fk_student_class foreign key(class_id) references class(cid)
    -> )charset=utf8 collate=utf8_general_ci engine=innodb comment '学生表';
Query OK, 0 rows affected (0.03 sec)

mysql> show tables;
+-----------------+
| Tables_in_test2 |
+-----------------+
| class           |
| student         |
+-----------------+
2 rows in set (0.00 sec)

mysql> desc student;
+----------+-----------------+------+-----+---------+----------------+
| Field    | Type            | Null | Key | Default | Extra          |
+----------+-----------------+------+-----+---------+----------------+
| sid      | int(11)         | NO   | PRI | NULL    | auto_increment |
| sname    | varchar(32)     | NO   |     | NULL    |                |
| gender   | enum('男','女') | NO   |     | 男      |                |
| class_id | int(11)         | YES  | MUL | NULL    |                |
+----------+-----------------+------+-----+---------+----------------+
4 rows in set (0.01 sec)
  • 创建教师表
mysql> create table teacher(
    -> tid int primary key auto_increment comment '主键ID',
    -> tname varchar(32) comment '老师名字'
    -> )charset=utf8 collate=utf8_general_ci engine=innodb comment='教师表';
Query OK, 0 rows affected (0.02 sec)

mysql> desc teacher;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| tid   | int(11)     | NO   | PRI | NULL    | auto_increment |
| tname | varchar(32) | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.01 sec)
  • 创建课程表
mysql> create table course(
    -> cid int primary key auto_increment comment '课程表',
    -> cname varchar(32) comment '课程名称',
    -> unique index_cname(cname),
    -> teacher_id int comment '关联教师表的外键',
    -> constraint fk_course_teacher foreign key(teacher_id) references teacher(t
id)
    -> )charset=utf8 collate=utf8_general_ci engine=innodb comment='课程表';
Query OK, 0 rows affected (0.03 sec)

mysql> desc course;
+------------+-------------+------+-----+---------+----------------+
| Field      | Type        | Null | Key | Default | Extra          |
+------------+-------------+------+-----+---------+----------------+
| cid        | int(11)     | NO   | PRI | NULL    | auto_increment |
| cname      | varchar(32) | YES  | UNI | NULL    |                |
| teacher_id | int(11)     | YES  | MUL | NULL    |                |
+------------+-------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)
  • 创建成绩表
mysql> create table score(
    ->      sid int primary key auto_increment comment '成绩表',
    ->      student_id int comment '添加关联学生表的外键字段',
    ->   constraint fk_score_student foreign key(student_id) references student(sid),
    ->      course_id int comment '添加关联课程表的外键字段',
    ->   constraint fk_score_course foreign key(course_id) references course(cid),
    ->      unique index_together(student_id,course_id) comment '将学生和成绩进行联合唯一索引',
    ->      number float(255,2) comment '学生成绩'
    ->      )charset=utf8 collate=utf8_general_ci engine=innodb comment='成绩表';
Query OK, 0 rows affected (0.03 sec)

mysql> desc score;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| sid        | int(11)      | NO   | PRI | NULL    | auto_increment |
| student_id | int(11)      | YES  | MUL | NULL    |                |
| course_id  | int(11)      | YES  | MUL | NULL    |                |
| number     | float(255,2) | YES  |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
4 rows in set (0.01 sec)

三、创建测试数据

  • 班级表添加数据
mysql> insert into class(caption)values('三年二班'),('一年三班'),('三年一班');
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0
  • 学生表添加数据
mysql> insert into student(sname,gender,class_id) values('钢蛋','女',1),('铁锤',
'女',1),('山炮','男',2);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0
  • 教师表添加数据
mysql> insert into teacher(tname) values('波多'),('苍空'),('饭岛');
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0
  • 课程表添加数据
mysql> insert into course(cname,teacher_id) values('生物',1),('体育',1),('物理',2);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0
  • 成绩表添加数据
mysql> insert into score(student_id,course_id,number) values(1,1,60),(1,2,59),(2
,2,100);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

四、操作数据表

1、查询“生物”课程比“物理”课程成绩高的所有学生的学号

分析:先查出所有生物课程成绩的学生;其次查出所有物理课程成绩的学生;最后将上述两个结果进行相连通过where语句查出符合要求的学生

#查出生物相关成绩的学生
mysql> select s.student_id,c.cname,s.number from course c left join score s on c
.cid=s.course_id where c.cname='生物';
+------------+-------+--------+
| student_id | cname | number |
+------------+-------+--------+
|          1 | 生物  |  60.00 |
+------------+-------+--------+
1 row in set (0.00 sec)

#查出物理成绩相关学生
mysql> select s.student_id,c.cname,s.number from course c left join score s on c
.cid=s.course_id where c.cname='物理';
+------------+-------+--------+
| student_id | cname | number |
+------------+-------+--------+
|       NULL | 物理  |   NULL |
+------------+-------+--------+
1 row in set (0.00 sec)

#查出符合条件的结果
mysql> select d.student_id,d.cname,d.number  from (select s.student_id,c.cname,s
.number from course c left join score s on c.cid=s.course_id where c.cname='生物')as d
    -> left join (select s.student_id,c.cname,s.number from course c left join score s on c.cid=s.course_id where c.cname='物理') as e on d.student_id=e.student
_id where
    -> d.number > ifnull(e.number,0);
+------------+-------+--------+
| student_id | cname | number |
+------------+-------+--------+
|          1 | 生物  |  60.00 |
+------------+-------+--------+
1 row in set (0.01 sec)

mysql>

2、查询平均成绩大于60分的同学的学号和平均成绩

分析:

  • 先查出所有同学的学号、各科成绩;
  • 其次是分组,根据学生的学号进行分组;
  • 计算出每一个学生的平均成绩;
  • 平均成绩大于60分的筛选出来;
#查出所有学生的学号和各科目的成绩
mysql> select sc.student_id,sc.course_id,number from student st left join score
sc on st.sid = sc.student_id;
+------------+-----------+--------+
| student_id | course_id | number |
+------------+-----------+--------+
|          1 |         1 |  60.00 |
|          1 |         2 |  59.00 |
|          2 |         2 | 100.00 |
|       NULL |      NULL |   NULL |
+------------+-----------+--------+
4 rows in set (0.00 sec)

#进行分组
mysql> select sc.student_id,sc.course_id,number from student st left join score
sc on st.sid = sc.student_id group by sc.student_id;
+------------+-----------+--------+
| student_id | course_id | number |
+------------+-----------+--------+
|       NULL |      NULL |   NULL |
|          1 |         1 |  60.00 |
|          2 |         2 | 100.00 |
+------------+-----------+--------+

#计算每一个学生的平均成绩
mysql> select sc.student_id,sc.course_id,number,avg(number) from student st left
 join score sc on st.sid = sc.student_id group by sc.student_id;
+------------+-----------+--------+-------------+
| student_id | course_id | number | avg(number) |
+------------+-----------+--------+-------------+
|       NULL |      NULL |   NULL |        NULL |
|          1 |         1 |  60.00 |   59.500000 |
|          2 |         2 | 100.00 |  100.000000 |
+------------+-----------+--------+-------------+
3 rows in set (0.00 sec)

#筛选出最后的结果
mysql> select sc.student_id,sc.course_id,number,avg(number) as stu_avg from stud
ent st left join score sc on st.sid = sc.student_id group by sc.student_id havin
g stu_avg > 60;
+------------+-----------+--------+------------+
| student_id | course_id | number | stu_avg    |
+------------+-----------+--------+------------+
|          2 |         2 | 100.00 | 100.000000 |
+------------+-----------+--------+------------+
1 row in set (0.00 sec)

3、查询所有同学的学号、姓名、选课数、总成绩

分析:

  • 查询所有的学生信息
  • 在进行统计选课数、总成绩时是针对每一个学生,所以必须以学生学号进行分组
  • 统计出最后的结果
mysql> select sc.student_id,st.sname,count(sc.course_id),sum(number) from studen
t st left join score sc on st.sid = sc.student_id group by sc.student_id;
+------------+-------+---------------------+-------------+
| student_id | sname | count(sc.course_id) | sum(number) |
+------------+-------+---------------------+-------------+
|       NULL | 山炮  |                   0 |        NULL |
|          1 | 钢蛋  |                   2 |      119.00 |
|          2 | 铁锤  |                   1 |      100.00 |
+------------+-------+---------------------+-------------+
3 rows in set (0.00 sec)

4、查询姓“李”的老师的个数

#使用正则表达式
mysql> select * from teacher where tname regexp '^李';
Empty set (0.00 sec)

5、查询没学过“叶平”老师课的同学的学号、姓名

分析:

  • 通过成绩表与学生表、课程表获取学生、课程以及教师id信息
  • 将上述查出的结果与教师表连表获取最终结果
#获取学生、课程教师id信息
mysql> select sc.student_id,st.sname,co.cname,co.teacher_id from score sc left j
oin student st on st.sid = sc.student_id left join course co on co.cid = sc.cour
se_id;
+------------+-------+-------+------------+
| student_id | sname | cname | teacher_id |
+------------+-------+-------+------------+
|          1 | 钢蛋  | 生物  |          1 |
|          1 | 钢蛋  | 体育  |          1 |
|          2 | 铁锤  | 体育  |          1 |
+------------+-------+-------+------------+
3 rows in set (0.00 sec)

#获取最终结果
mysql> select a.student_id,a.sname from (select sc.student_id,st.sname,co.cname,
co.teacher_id from score sc left join student st on st.sid = sc.student_id left
join course co on co.cid = sc.course_id) as a left join teacher te on a.teacher_
id=te.tid where te.tname != '叶平';
+------------+-------+
| student_id | sname |
+------------+-------+
|          1 | 钢蛋  |
|          1 | 钢蛋  |
|          2 | 铁锤  |
+------------+-------+
3 rows in set (0.00 sec)

6、查询学过“001”并且也学过编号“002”课程的同学的学号、姓名

分析:

  • 先查出学习001课程所有的学生信息
  • 再查出学习002课程所有学生的信息
  • 上面查出的结果再作为查询结果集,查出符合条件的结果,条件就是这两个课程的学生id是一样的
#所有学生的信息
mysql> select st.sid,st.sname,co.cid,co.cname from score sc left join student st

    ->  on sc.student_id = st.sid left join course co on sc.course_id = co.cid;
+------+-------+------+-------+
| sid  | sname | cid  | cname |
+------+-------+------+-------+
|    1 | 钢蛋  |    1 | 生物  |
|    1 | 钢蛋  |    2 | 体育  |
|    2 | 铁锤  |    2 | 体育  |
+------+-------+------+-------+
3 rows in set (0.00 sec)

#001课程学生信息
mysql>  select b.sid,b.sname from
    ->  (select a.sid,a.sname,a.cid,a.cname from (select st.sid,st.sname,co.cid,co.cname from score sc left join student st
    ->  on sc.student_id = st.sid left join course co on sc.course_id = co.cid)as a where a.cid=2) as b;
+------+-------+
| sid  | sname |
+------+-------+
|    2 | 铁锤  |
|    1 | 钢蛋  |
+------+-------+
2 rows in set (0.00 sec)

#002课程学生信息
mysql> select c.sid,c.sname from (select a.sid,a.sname,a.cid,a.cname from (select st.sid,st.sname,co.cid,co.cname from score sc left join student st
    ->  on sc.student_id = st.sid left join course co on sc.course_id = co.cid)
as a where a.cid=1) as c;
+------+-------+
| sid  | sname |
+------+-------+
|    1 | 钢蛋  |
+------+-------+
1 row in set (0.00 sec)

#利用同一个学生作为条件进行查询
mysql>  select b.sid,b.sname from
    ->  (select a.sid,a.sname,a.cid,a.cname from (select st.sid,st.sname,co.cid,co.cname from score sc left join student st
    ->  on sc.student_id = st.sid left join course co on sc.course_id = co.cid)as a where a.cid=2) as b,
    ->
    -> (select a.sid,a.sname,a.cid,a.cname from (select st.sid,st.sname,co.cid,co.cname from score sc left join student st
    ->  on sc.student_id = st.sid left join course co on sc.course_id = co.cid)as a where a.cid=1) as c
    ->
    ->  where b.sid = c.sid;
+------+-------+
| sid  | sname |
+------+-------+
|    1 | 钢蛋  |
+------+-------+
1 row in set (0.00 sec)

7、查询学过“叶平”老师所教的所有课的同学的学号、姓名

 分析:

  • 通过连表查出所有学生、教师、课程相关信息
  • 进行过滤
#获取所有信息
mysql> select st.sid,st.sname,te.tname,co.cname from score sc left join course c
o on sc.course_id = co.cid left join teacher te on co.teacher_id = te.tid left j
oin student st on sc.student_id = st.sid;
+------+-------+-------+-------+
| sid  | sname | tname | cname |
+------+-------+-------+-------+
|    1 | 钢蛋  | 波多  | 生物  |
|    1 | 钢蛋  | 波多  | 体育  |
|    2 | 铁锤  | 波多  | 体育  |
+------+-------+-------+-------+
3 rows in set (0.00 sec)

#过滤获取符合要求的结果
mysql> select st.sid,st.sname,te.tname,co.cname from score sc left join course c
o on sc.course_id = co.cid left join teacher te on co.teacher_id = te.tid left j
oin student st on sc.student_id = st.sid where te.tname='叶平';
Empty set (0.00 sec)

8、查询课程编号“002”的成绩比课程编号“001”课程低的所有同学的学号、姓名

分析:

  • 查出课程编号“002”成绩的所有同学信息
  • 查出课程编号“001”成绩的所有同学信息
  • 通过where语句进行筛选(条件是同一个同学、002成绩小于001成绩)
#001成绩的同学信息
mysql> select st.sid,st.sname,sc.number from score sc left join course co on sc.
course_id = co.cid left join student st on sc.student_id = st.sid where co.cid=1
;
+------+-------+--------+
| sid  | sname | number |
+------+-------+--------+
|    1 | 钢蛋  |  60.00 |
+------+-------+--------+
1 row in set (0.00 sec)

#002成绩的同学信息
mysql> select st.sid,st.sname,sc.number from score sc left join course co on sc.
course_id = co.cid left join student st on sc.student_id = st.sid where co.cid=2
;
+------+-------+--------+
| sid  | sname | number |
+------+-------+--------+
|    1 | 钢蛋  |  59.00 |
|    2 | 铁锤  | 100.00 |
+------+-------+--------+
2 rows in set (0.00 sec)

#过滤条件
mysql> select a.sid,a.sname,a.number
    -> from
    -> (select st.sid,st.sname,sc.number from score sc left join course co on sc
.
    -> course_id = co.cid left join student st on sc.student_id = st.sid where c
o.cid=1) as a,
    ->
    -> (select st.sid,st.sname,sc.number from score sc left join course co on sc
.
    -> course_id = co.cid left join student st on sc.student_id = st.sid where c
o.cid=2) as b
    ->
    -> where a.sid = b.sid and a.number > b.number;
+------+-------+--------+
| sid  | sname | number |
+------+-------+--------+
|    1 | 钢蛋  |  60.00 |
+------+-------+--------+
1 row in set (0.00 sec)

9、查询有课程成绩小于60分的同学的学号、姓名

分析:

  • 通过连表获取所有同学的学号、姓名、课程、成绩信息
  • 通过where过滤出符合条件的信息
#所有学生及成绩信息
mysql> select st.sid,st.sname,co.cname,sc.number from score sc left join student
 st on sc.student_id = st.sid left join course co on sc. course_id = co.cid;
+------+-------+-------+--------+
| sid  | sname | cname | number |
+------+-------+-------+--------+
|    1 | 钢蛋  | 生物  |  60.00 |
|    1 | 钢蛋  | 体育  |  59.00 |
|    2 | 铁锤  | 体育  | 100.00 |
+------+-------+-------+--------+
3 rows in set (0.00 sec)

#过滤
mysql> select st.sid,st.sname,co.cname,sc.number from score sc left join student
 st on sc.student_id = st.sid left join course co on sc. course_id = co.cid wher
e number < 60;
+------+-------+-------+--------+
| sid  | sname | cname | number |
+------+-------+-------+--------+
|    1 | 钢蛋  | 体育  |  59.00 |
+------+-------+-------+--------+
1 row in set (0.00 sec)

10、查询没有学全所有课的同学的学号、姓名

分析:

  • 通过课程表计算出所有课程的数目(count)
  • 计算出每一个同学(group by)所拥有的课程数量(count)
  • 将上述结果作为结果集使用where过滤
#所有课程数量
mysql> select count(co.cid) as co_count  from course co;
+----------+
| co_count |
+----------+
|        3 |
+----------+
1 row in set (0.00 sec)

#每一个同学拥有的课程数量
mysql> select st.sid,st.sname,count(co.cid) as st_co_count from score sc left jo
in student st on sc.student_id = st.sid left join course co on sc.course_id = co
.cid group by st.sid;
+------+-------+-------------+
| sid  | sname | st_co_count |
+------+-------+-------------+
|    1 | 钢蛋  |           2 |
|    2 | 铁锤  |           1 |
+------+-------+-------------+
2 rows in set (0.00 sec)

#进行过滤
mysql> select a.sid,a.sname,a.st_co_count from (select st.sid,st.sname,count(co.
cid) as st_co_count from score sc left join student st on sc.student_id = st.sid
 left join course co on sc.course_id = co.cid group by st.sid) as a,
    -> (select count(co.cid) as co_count  from course co) as b
    -> where a.st_co_count < b.co_count;
+------+-------+-------------+
| sid  | sname | st_co_count |
+------+-------+-------------+
|    1 | 钢蛋  |           2 |
|    2 | 铁锤  |           1 |
+------+-------+-------------+
2 rows in set (0.00 sec)

11、查询至少有一门课与学号为“001”的同学所学相同的同学的学号和姓名

分析:

  • 查找“001”的同学的所有课程信息
  • 查找除“001”“同学以外的同学所有课程的信息
  • 通过课程名称进行过滤
#所有同学的所有课程信息
mysql> select st.sid,st.sname,co.cname from score sc left join student st on st.
sid = sc.student_id left join course co on sc.course_id = co.cid;
+------+-------+-------+
| sid  | sname | cname |
+------+-------+-------+
|    1 | 钢蛋  | 生物  |
|    1 | 钢蛋  | 体育  |
|    2 | 铁锤  | 体育  |
+------+-------+-------+
3 rows in set (0.00 sec)

#001同学课程的所有信息
mysql> select st.sid,st.sname,co.cname from score sc left join student st on st.
sid = sc.student_id left join course co on sc.course_id = co.cid where st.sid=1;

+-----+-------+-------+
| sid | sname | cname |
+-----+-------+-------+
|   1 | 钢蛋  | 生物  |
|   1 | 钢蛋  | 体育  |
+-----+-------+-------+
2 rows in set (0.00 sec)

#除001同学以外的同学课程信息
mysql> select st.sid,st.sname,co.cname from score sc left join student st on st.
sid = sc.student_id left join course co on sc.course_id = co.cid where st.sid !=
1;
+------+-------+-------+
| sid  | sname | cname |
+------+-------+-------+
|    2 | 铁锤  | 体育  |
+------+-------+-------+
1 row in set (0.00 sec)

#通过课程名字进行过滤
mysql> select a.sid,a.sname,a.cname from
    -> (select st.sid,st.sname,co.cname from score sc left join student st on st
.
    -> sid = sc.student_id left join course co on sc.course_id = co.cid where st
.sid = 1) as a,
    -> (select st.sid,st.sname,co.cname from score sc left join student st on st
.
    -> sid = sc.student_id left join course co on sc.course_id = co.cid where st
.sid != 1) as b
    -> where b.cname regexp a.cname;
+------+-------+-------+
| sid  | sname | cname |
+------+-------+-------+
|    1 | 钢蛋  | 体育  |
+------+-------+-------+
1 row in set (0.00 sec)

12、查询和“002”号的同学学习的课程完全相同的其他同学学号和姓名

分析:

这个和上面的差不多,只不过在最后的筛选条件处做一些改变

mysql> select a.sid,a.sname,a.cname from
    -> (select st.sid,st.sname,co.cname from score sc left join student st on st
.
    -> sid = sc.student_id left join course co on sc.course_id = co.cid where st
.sid != 2) as a,
    -> (select st.sid,st.sname,co.cname from score sc left join student st on st
.
    -> sid = sc.student_id left join course co on sc.course_id = co.cid where st
.sid = 2) as b
    -> where b.cname = a.cname;
+------+-------+-------+
| sid  | sname | cname |
+------+-------+-------+
|    1 | 钢蛋  | 体育  |
+------+-------+-------+
1 row in set (0.00 sec)

13、删除学习“叶平”老师课的SC表记录

 分析:

  • 先查找出叶平老师所教课程的所有cid
  • 根据课程cid删除对应的记录
#叶平老师所教课程的cid
mysql> select co.cid from course co left join teacher te on co.teacher_id=te.tid
 where te.tname='叶平';
Empty set (0.00 sec)

#根据cid删除记录
mysql>  delete from score where course_id in (select co.cid from course co left
join teacher te on co.teacher_id=te.tid where te.tname='叶平');
Query OK, 0 rows affected (0.00 sec)

......待续

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!