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;
好的,我来为您解答MySQL的SQL语句练习题(一)。 1. 创建一个名为“test”的数据库。 ``` CREATE DATABASE test; ``` 2. 在“test”数据库中创建一个名为“student”的数据表,包含以下字段:学号(id,整型,主键),姓名(name,字符串类型,不超过20个字符),年龄(age,整型),性别(gender,字符串类型,不超过10个字符),成绩(score,整型)。 ``` USE test; CREATE TABLE student ( id INT PRIMARY KEY, name VARCHAR(20), age INT, gender VARCHAR(10), score INT ); ``` 3. 插入以下数据到“student”数据表中: ``` INSERT INTO student VALUES (1, 'Tom', 18, 'male', 80), (2, 'Jerry', 19, 'male', 85), (3, 'Lily', 18, 'female', 90), (4, 'Lucy', 20, 'female', 95); ``` 4. 查询“student”数据表中所有学生姓名和年龄。 ``` SELECT name, age FROM student; ``` 5. 查询“student”数据表中所有学生的学号、姓名和成绩,并按成绩从高到低排序。 ``` SELECT id, name, score FROM student ORDER BY score DESC; ``` 6. 查询“student”数据表中所有学生的平均年龄。 ``` SELECT AVG(age) FROM student; ``` 7. 查询“student”数据表中成绩大于等于90分的学生姓名和成绩。 ``` SELECT name, score FROM student WHERE score >= 90; ``` 8. 将“student”数据表中学号为3的学生的成绩更新为100分。 ``` UPDATE student SET score = 100 WHERE id = 3; ``` 9. 删除“student”数据表中年龄小于19岁的学生。 ``` DELETE FROM student WHERE age < 19; ``` 以上是MySQL的SQL语句练习题(一)的解答,希望能对您有所帮助。如果您有任何疑问或需要进一步的帮助,请随时向我提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值