MYSQL--SELECT练习题1

一.问题

有 3 个表 STUDENT(学生表),LESSON(课程表),TIMETABLE(学生选课表)。其中

STUDENT(SNO,SNAME)代表(学号,姓名)

(CNO,CNAME,CTEACHER)代表(课号,课名,教师)

TIMETABLE(ID,SNO,CNO,SCGRADE)代表(序号,学号,课号,成绩)

问题:

  1. 找出没选过“黎明”老师的所有学生姓名。

  2. 列出 2 门以上(含 2 门)不及格学生姓名及平均成绩。

  3. 既学过 1 号课程又学过 2 号课所有学生的姓名。

建表代码如下

START TRANSACTION;

DROP TABLE IF EXISTS TIMETABLE;
DROP TABLE IF EXISTS STUDENT;
DROP TABLE IF EXISTS LESSON;


CREATE TABLE STUDENT
(
 SNO VARCHAR(200) PRIMARY KEY,
 SNAME VARCHAR(200)
)DEFAULT CHARSET = 'utf8';

CREATE TABLE LESSON
(
 CNO VARCHAR(200) PRIMARY KEY,
 CNAME VARCHAR(200),
 CTEACHER VARCHAR(200)
) DEFAULT CHARSET = 'utf8';

CREATE TABLE TIMETABLE
(
 ID  INT PRIMARY KEY AUTO_INCREMENT,
 SNO VARCHAR(200),
 CNO VARCHAR(200),
 SCGRADE VARCHAR(200),
 FOREIGN KEY(SNO) REFERENCES STUDENT(SNO),
 FOREIGN KEY(CNO) REFERENCES LESSON(CNO)
)DEFAULT CHARSET = 'utf8';


INSERT INTO LESSON ( CNO, CNAME, CTEACHER ) VALUES ( '1', '语文', '张'); 
INSERT INTO LESSON ( CNO, CNAME, CTEACHER ) VALUES ( '2', '政治', '王'); 
INSERT INTO LESSON ( CNO, CNAME, CTEACHER ) VALUES ( '3', '英语', '李'); 
INSERT INTO LESSON ( CNO, CNAME, CTEACHER ) VALUES ( '4', '数学', '赵'); 
INSERT INTO LESSON ( CNO, CNAME, CTEACHER ) VALUES ( '5', '物理', '黎明'); 

INSERT INTO STUDENT ( SNO, SNAME ) VALUES ( '1', '学生 1'); 
INSERT INTO STUDENT ( SNO, SNAME ) VALUES ( '2', '学生 2'); 
INSERT INTO STUDENT ( SNO, SNAME ) VALUES ( '3', '学生 3'); 
INSERT INTO STUDENT ( SNO, SNAME ) VALUES ( '4', '学生 4'); 

INSERT INTO TIMETABLE ( SNO, CNO, SCGRADE ) VALUES ( '1', '1', '40'); 
INSERT INTO TIMETABLE ( SNO, CNO, SCGRADE ) VALUES ( '1', '2', '30'); 
INSERT INTO TIMETABLE ( SNO, CNO, SCGRADE ) VALUES ( '1', '3', '20'); 
INSERT INTO TIMETABLE ( SNO, CNO, SCGRADE ) VALUES ( '1', '4', '80');
INSERT INTO TIMETABLE ( SNO, CNO, SCGRADE ) VALUES ( '1', '5', '60'); 
INSERT INTO TIMETABLE ( SNO, CNO, SCGRADE ) VALUES ( '2', '1', '60'); 
INSERT INTO TIMETABLE ( SNO, CNO, SCGRADE ) VALUES ( '2', '2', '60'); 
INSERT INTO TIMETABLE ( SNO, CNO, SCGRADE ) VALUES ( '2', '3', '60'); 
INSERT INTO TIMETABLE ( SNO, CNO, SCGRADE ) VALUES ( '2', '4', '60'); 
INSERT INTO TIMETABLE ( SNO, CNO, SCGRADE ) VALUES ( '2', '5', '40'); 
INSERT INTO TIMETABLE ( SNO, CNO, SCGRADE ) VALUES ( '3', '1', '60'); 
INSERT INTO TIMETABLE ( SNO, CNO, SCGRADE ) VALUES ( '3', '3', '80'); 


commit;

二.解析

问题1

找出没选过“黎明”老师的所有学生姓名。

思路:首先找出所有选过”黎明“老师课程的学生,将其存储在视图LimingStudent中。然后用STUDENT表与LimingStudent进行比对,即可找出剩下没选过”黎明“老师课程的学生。

step1: 利用表连接,将timetable中的课程号换成上课老师的姓名

select t.id,t.sno,l.cteacher,t.scgrade from timetable t join lesson l on t.cno = l.cno order by id;

在这里插入图片描述

step2: 找到所有选过“黎明”老师课程的学生编号

select a.sno from (select t.id,t.sno,l.cteacher,t.scgrade from timetable t join lesson l on t.cno = l.cno order by id) a where cteacher = '黎明';

在这里插入图片描述

PS:上面语句中的表a 即为step1中的表

step3: 将step2中的查询结果存储在视图LimingStudent中

create view LimingStudent as select a.sno from (select t.id,t.sno,l.cteacher,t.scgrade from timetable t join lesson l on t.cno = l.cno order by id) a where cteacher = '黎明';

step4: 将LimingStudent中的学生编号与Student中的学生编号进行比对,找到没选过“黎明”课的学生.

 select s.sname from student s join LimingStudent on s.sno not in (select sno from LimingStudent);

在这里插入图片描述

step5: 由于表连接是两个表的所有表项按照笛卡尔积一一比对,所以结果有重复。因此不要忘了要去重

 select distinct s.sname from student s join LimingStudent on s.sno not in (select sno from LimingStudent);
 

在这里插入图片描述

最后记得删除视图!

完整代码为

create view LimingStudent as select a.sno from (select t.id,t.sno,l.cteacher,t.scgrade from timetable t join lesson l on t.cno = l.cno order by id) a where cteacher = '黎明';
 select distinct s.sname from student s join LimingStudent on s.sno not in (select sno from LimingStudent);
 drop view LimingStudent;

问题2

列出 2 门以上(含 2 门)不及格学生姓名及平均成绩。

思路: 找到两门以上不及格的学生编号,而后利用表连接找出学生姓名,利用分组函数avg找出平均成绩。

step1: 找到挂过科的学生的学生编号

select sno,cno,scgrade from timetable where scgrade < 60;

step2: 将step1中的表按照sno进行分组,找出每个学生不及格的课程数目

select t.sno,count(t.cno)count from(select sno,cno,scgrade from timetable where scgrade < 60) t group by t.sno;

在这里插入图片描述

step3: 利用step2中的表,找到挂科数大于2门的学生编号

 select t1.sno from  (select t.sno,count(t.cno) count from(select sno,cno,scgrade from timetable where scgrade < 60) t group by t.sno) t1 where t1.count>=2;

在这里插入图片描述

step4: 将step3中的结果创建一个视图存储起来。

create view view1 as select t1.sno from  (select t.sno,count(t.cno) count from(select sno,cno,scgrade from timetable where scgrade < 60) t group by t.sno) t1 where t1.count>=2;

step5: 利用表连接查询对应的学生姓名

 select s.sname,v.sno from student s join view1 v on s.sno = v.sno;

在这里插入图片描述

step6: 利用分组函数avg计算出大于2门不及格的学生的平均成绩。注意sql语句的where部分,要用in来判断,而不能用=,如果view1中的数据大于1,用=会报错。

 select sno,avg(scgrade) avg from timetable where sno in (select sno from view1) group by sno;

在这里插入图片描述

step7: 将step5的结果与step6的结果利用表连接合并

 select t1.sname ,t2.avg from ( select s.sname,v.sno from student s join view1 v on s.sno = v.sno) t1 join ( select sno,avg(scgrade) avg from timetable where sno in (select sno from view1) group by sno) t2 on t1.sno = t2.sno;

在这里插入图片描述

完整代码

create view view1 as select t1.sno from  (select t.sno,count(t.cno) count from(select sno,cno,scgrade from timetable where scgrade < 60) t group by t.sno) t1 where t1.count>=2;
select t1.sname ,t2.avg from ( select s.sname,v.sno from student s join view1 v on s.sno = v.sno) t1 join ( select sno,avg(scgrade) avg from timetable where sno in (select sno from view1) group by sno) t2 on t1.sno = t2.sno;
drop view view1;

问题3

既学过 1 号课程又学过 2 号课所有学生的姓名。

思路:首先找出学过1号课程的学生姓名,然后找出学过2号课程的学生姓名,最后取交集。

step1: 先在timetable表中找到选1号课程学生的学生编号

select sno,cno from timetable where cno = 1;

在这里插入图片描述

step2: 利用表连接,找到选1号课程对应的学生姓名

select s.sname,t.cno from (select sno,cno from timetable where cno = 1) t join student s on t.sno = s.sno;

在这里插入图片描述

step3: 将step2的结果存储在一个视图中

create view view1 as  select s.sname,t.cno from (select sno,cno from timetable where cno = 1) t join student s on t.sno = s.sno;

step4: 按照上面的步骤选出选择2号课程的学生姓名,并存储在一个视图中

create view view2 as  select s.sname,t.cno from (select sno,cno from timetable where cno = 2) t join student s on t.sno = s.sno;

step5: 将两个视图连接查询,找出同时存在于两个视图中的学生姓名

select v1.sname from view1 v1 join view2 v2 on v1.sname = v2.sname;

在这里插入图片描述

完整代码

create view view1 as  select s.sname,t.cno from (select sno,cno from timetable where cno = 1) t join student s on t.sno = s.sno;
create view view2 as  select s.sname,t.cno from (select sno,cno from timetable where cno = 2) t join student s on t.sno = s.sno;
select v1.sname from view1 v1 join view2 v2 on v1.sname = v2.sname;
drop view view1;
drop view view2;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值