一、表关系
二、创建数据库和表
(一)创建数据库
创建数据库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)