【MYSQL数据库综合练习】第一部分

MySQL通关练习题目

运行创建数据库

drop table if exists student;

drop table if exists teacher;

drop table if exists course;

drop table if exists sc;

create table student(

sno varchar(10) primary key,

sname varchar(20),

sage int,

ssex varchar(5)

);

create table teacher(

tno varchar(10) primary key,

tname varchar(20)

);

create table course(

cno varchar(10),

cname varchar(20),

tno varchar(20),

constraint pk_course primary key (cno,tno)

);

create table sc(

sno varchar(10),

cno varchar(10),

score decimal(8,2),

constraint pk_sc primary key (sno,cno)

);

/*初始化学生表的数据/

insert into student values (‘s001’,‘张三’,23,‘男’);

insert into student values (‘s002’,‘李四’,23,‘男’);

insert into student values (‘s003’,‘吴鹏’,25,‘男’);

insert into student values (‘s004’,‘琴沁’,20,‘女’);

insert into student values (‘s005’,‘王丽’,20,‘女’);

insert into student values (‘s006’,‘李波’,21,‘男’);

insert into student values (‘s007’,‘刘玉’,21,‘男’);

insert into student values (‘s008’,‘萧蓉’,21,‘女’);

insert into student values (‘s009’,‘陈萧晓’,23,‘女’);

insert into student values (‘s010’,‘陈美’,22,‘女’);

/初始化教师表*****/

insert into teacher values (‘t001’, ‘刘阳’);

insert into teacher values (‘t002’, ‘谌燕’);

insert into teacher values (‘t003’, ‘胡明星’);

/初始化课程表*************/

insert into course values (‘c001’,‘J2SE’,‘t002’);

insert into course values (‘c002’,‘Java Web’,‘t002’);

insert into course values (‘c003’,‘SSH’,‘t001’);

insert into course values (‘c004’,‘Oracle’,‘t001’);

insert into course values (‘c005’,‘SQL SERVER 2005’,‘t003’);

insert into course values (‘c006’,‘C#’,‘t003’);

insert into course values (‘c007’,‘JavaScript’,‘t002’);

insert into course values (‘c008’,‘DIV+CSS’,‘t001’);

insert into course values (‘c009’,‘PHP’,‘t003’);

insert into course values (‘c010’,‘EJB3.0’,‘t002’);

/初始化成绩表********/

insert into sc values (‘s001’,‘c001’,78.9);

insert into sc values (‘s002’,‘c001’,80.9);

insert into sc values (‘s003’,‘c001’,81.9);

insert into sc values (‘s004’,‘c001’,60.9);

insert into sc values (‘s001’,‘c002’,82.9);

insert into sc values (‘s002’,‘c002’,72.9);

insert into sc values (‘s003’,‘c002’,81.9);

insert into sc values (‘s001’,‘c003’,59);

insert into sc values (‘s001’,‘c004’,78.9);

insert into sc values (‘s002’,‘c004’,80.9);

insert into sc values (‘s003’,‘c005’,81.9);

insert into sc values (‘s004’,‘c005’,60.9);

insert into sc values (‘s001’,‘c006’,82.9);

insert into sc values (‘s002’,‘c006’,72.9);

insert into sc values (‘s003’,‘c007’,81.9);

insert into sc values (‘s001’,‘c007’,59);

insert into sc values (‘s005’,‘c001’,80.9);

insert into sc values (‘s006’,‘c001’,81.9);

insert into sc values (‘s007’,‘c001’,90.9);

insert into sc values (‘s004’,‘c002’,75);

insert into sc values (‘s005’,‘c002’,71.2);

insert into sc values (‘s006’,‘c002’,85.9);

insert into sc values (‘s007’,‘c003’,59);

insert into sc values (‘s004’,‘c004’,77.9);

insert into sc values (‘s005’,‘c004’,84.9);

insert into sc values (‘s006’,‘c005’,82.9);

insert into sc values (‘s007’,‘c005’,67.9);

insert into sc values (‘s004’,‘c006’,62.9);

insert into sc values (‘s006’,‘c006’,92.9);

insert into sc values (‘s007’,‘c007’,35.9);

insert into sc values (‘s008’,‘c007’,69);

练习:
注意:以下练习中的数据是根据初始化到数据库中的数据来写的SQL 语句,请大家务必注意。

1、查询“c001”课程比“c002”课程成绩高的所有学生的学号;

SELECT
  sc1.sno 
FROM sc sc1,sc sc2 
WHERE
sc1.sno = sc2.sno AND sc1.cno = 'c001' AND sc2.cno = 'c002' AND sc1.score > sc2.score

知识点:

1、子查询(查询结果作为数据表)

2、聚合函数的使用。(没有在聚合函数中的字段,必须包含在group by子句中)——分组统计。

聚合函数总共有5个(sum,count,max,min,avg)。作用:统计

3、case… when…else…end(相当与程序里面的if…else…)

(1) Case…when…when…else…end

(2) Case when…when…else…end

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

方法一:

SELECT sno,AVG(score) FROM sc
WHERE sno IN (SELECT sno FROM sc GROUP BY sno HAVING AVG(score)>60)
GROUP BY sno
HAVING AVG(score)

知识点:

1、子查询

2、聚合函数

3、统计结果列不能用在where条件中

方法二:

SELECT sno,AVG(score) FROM sc
GROUP BY sno
HAVING AVG(score)>60

知识点:

1、having–用来过滤统计字段

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

分析:学号,姓名在student表

​ 选课数:统计字段–>来源(sc 表)

总成绩:统计字段(来源:SC表)

结果sql:

SELECT student.sno,student.sname,COUNT(sc.cno),SUM(sc.score) 
FROM student RIGHT JOIN sc ON sc.sno=student.sno
GROUP BY student.sno,student.sname

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

分析:字段(老师个数)—来源(teacher表)

涉及:模糊查询

SELECT COUNT(tname) FROM teacherWHERE tname LIKE '刘%'

5、查询没学过“谌燕”老师课的同学的学号、姓名;

分析:

1、查询字段(学号,姓名)–student表

2、条件:teacher表姓名=‘谌燕’–>tno->(course–>cno)–>(sc->查找没有记录的)

SELECT sno,sname 
FROM student
WHERE sno NOT IN (SELECT sno FROM scWHERE cno IN (SELECT cno FROM course INNER JOIN teacherWHERE tname='谌燕'))

6、查询学过“c001”并且也学过编号“c002”课程的同学的学号、姓名;

方法一:

分析:结果(学号,姓名–>student)

条件:–>sc表(查询出既有c001课程和c002课程的学号)—>先将有c001的学号找到,然后再找还有c002的。

SELECT sno,sname 
FROM student
WHERE sno IN (SELECT sno FROM sc WHERE cno='c001' AND sno IN (SELECT sno FROM sc WHERE cno='c002'))

知识点:in(集合)关键字。作为查询条件。例如:sno in(‘002’,’003’)–>表示,sno等于002或者003的结果。 在in(集合)的集合中,我们可以使用子查询,注意:子查询的结果应该是只有一列

方法二:

分析:如果只需要查询学过c001课程的学生

SELECT sno FROM studentWHERE sno IN (SELECT sno FROM sc WHERE cno='c001')

在这个结果的基础上再去找学过c002的学生

SELECT sno,sname 
FROM student 
WHERE sno IN (SELECT sno FROM studentWHERE sno IN (SELECT sno FROM sc WHERE cno='c001')) AND sno IN (SELECT sno FROM sc WHERE cno='c002')

7、查询学过“谌燕”老师所教的所有课的同学的学号、姓名;

分析:结果(student–>学号,姓名)

条件:teacher(tname=’谌燕’)–>course(所有的cno)==》cno的集合

SELECT cno FROM course INNER JOIN teacher ON course.tno=teacher.tnoWHERE teacher.tname='谌燕'

==>分组统计(某个学生选了多少门‘谌燕’老师的课程)

SELECT COUNT(cno) 
FROM student INNER JOIN sc ON student.sno=sc.sno
WHERE cno IN (SELECT cno FROM course INNER JOIN teacher ON course.tno=teacher.tnoWHERE teacher.tname='谌燕')GROUP BY sc.sno

==>判断学生选课数量等于‘谌燕’老师所教课程的数量

SELECT student.sno,student.sname 
FROM student INNER JOIN sc ON student.sno=sc.sno
WHERE cno IN (SELECT cno FROM course INNER JOIN teacher ON course.tno=teacher.tnoWHERE teacher.tname='谌燕')
GROUP BY student.sno,student.sname
-- 用having判断学生选课数量等于‘谌燕’老师所教课程的数量
HAVING COUNT(cno)=(SELECT COUNT(cno) FROM course INNER JOIN teacher ON course.tno=teacher.tnoWHERE teacher.tname='谌燕')

*8、查询课程编号“c002”的成绩比课程编号“c001”课程低的所有同学的学号、姓名;

select student.sno,student.sname from student where student.sno in (
select sc2.sno from sc sc1 ,sc sc2 where sc1.sno=sc2.sno and sc1.cno='c001' and sc2.cno='c002' and sc2.score<sc1.score)

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

SELECT sno,sname FROM student

-- 逆向思维,先求有一个60分以上的学号,再用NOT IN 求解

WHERE sno NOT IN (SELECT sno FROM sc WHERE score>=60)

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

SELECT student.sno 
FROM sc RIGHT JOIN student ON student.sno=sc.sno
GROUP BY student.sno 
HAVING COUNT(sc.cno) < (SELECT COUNT(cno) FROM course)

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

select sno,sname
from student
where sno in (
select sno 
from sc
where cno in(
select cno
from sc
where sno='s008')) and sno !='s008'

12、查询至少学过学号为“s001”同学所有课的其他同学学号和姓名;

分析:

1、找到学号s001的同学所学的所有课程

2、找到学过这些课程的同学名单

SELECT DISTINCT student.sno,student.sname 
FROM student INNER JOIN sc ON student.sno=sc.sno
WHERE sc.cno IN (SELECT cno FROM sc WHERE sno='s001') AND student.sno!='s001'

知识点:in和exists的区别

1、in()确定给定的值是否与子查询或列表中的值相匹配。in在查询的时候,首先查询子查询的表,然后将内表和外表做一个笛卡尔积,然后按照条件进行筛选。所以相对内表比较小的时候,in的速度较快。

2、exists指定一个子查询,检测行的存在。遍历循环外表,然后看外表中的记录有没有和内表的数据一样的。匹配上就将结果放入结果集中。

3、区别及使用场景:内表结果大用exists;内表结果小用In

not in 和not exists

如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;而not extsts 的子查询依然能用到表上的索引。所以无论那个表大,用not exists都比not in要快。

*13、把“SC”表中“谌燕”老师教的课的成绩都更改为此课程的平均成绩;

UPDATE sc SET score=(SELECT s.a FROM (SELECT avgsco.a,avgsco.cno FROM (SELECT cno,AVG(score) AS a FROM sc WHERE cno IN (SELECT cno FROM course INNER JOIN teacher ON teacher.tno=course.tno WHERE teacher.tname='谌燕')
                                                                       
-- 不对的地方:没办法将平均成绩和update里要修改的成绩对应
GROUP BY cno) AS avgsco) as s WHERE s.cno=cno) 
WHERE cno IN (SELECT cno FROM sc WHERE cno IN (SELECT cno FROM course INNER JOIN teacher ON teacher.tno=course.tno WHERE teacher.tname='谌燕'))

-- UPDATE在更新这个表和数据时又查询了它,而查询的数据又做了更新的条件,所以用别名,但是平均成绩有多行,再对这个表查询,产生一个包含平均成绩和课程号的表s
SELECT s.a FROM (SELECT avgsco.a,avgsco.cno FROM (SELECT cno,AVG(score) AS a FROM sc WHERE cno IN (SELECT cno FROM course INNER JOIN teacher ON teacher.tno=course.tno WHERE teacher.tname='谌燕')
GROUP BY cno) AS avgsco) as s WHERE s.cno=sc.cno

-- 求所教课程
SELECT cno FROM sc 
WHERE cno IN (SELECT cno FROM course INNER JOIN teacher ON teacher.tno=course.tno WHERE teacher.tname='谌燕')

-- 求所教课程的平均成绩
SELECT AVG(score) FROM sc WHERE cno IN (SELECT cno FROM course INNER JOIN teacher ON teacher.tno=course.tno WHERE teacher.tname='谌燕')
GROUP BY cno

订正

update sc s1 join (select sc,cno,avg(sc.score) avgscore form course,teacher,sc
where course.tno=teacher.tno
and course.cno=sc.cno
and teacher.tname='谌燕'
group by sc.cno) s2 ON s1.cno = s2.cno
SET s1.score=s2.avgscore

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

-- s001同学学习的课程
SELECT cno FROM sc WHERE sno='s001'

-- c001 c002 c003 c004 c006 c007

-- 借鉴思路:逆向思维先求cno有一门和s001不一样的,就可以排除一部分,之后其他的都是要么少于s001的,要么是和s001相同的
SELECT sno FROM sc
WHERE cno NOT IN ((SELECT sc.cno FROM sc WHERE sc.sno='s001'))
GROUP BY sno

-- 此时再对sno反选,选出所选课要么少于s001的,要么是和s001相同的
SELECT sno FROM sc
WHERE sno NOT IN 
(SELECT sno FROM sc
WHERE cno NOT IN ((SELECT sc.cno FROM sc WHERE sc.sno='s001'))
GROUP BY sno
) AND sno<>'s001'
GROUP BY sno 

-- 再对比符合条件的数量
HAVING COUNT(cno)=(SELECT COUNT(cno) FROM sc WHERE sc.sno='s001')

15、删除学习“谌燕”老师课的SC 表记录;

select from sc where cno IN (
select cno from course where tno in(
select tno from teacher where tname='谌燕'))

16、向SC 表中插入一些记录,这些记录要求符合以下条件:没有上过编号“c002”课程的同学学号、“c002”号课的平均成绩;

-- “c002”号课的平均成绩
SELECT AVG(score)  FROM sc
WHERE cno='c002'

-- 没有上过编号c002课程的同学学号
SELECT DISTINCT sno FROM sc
WHERE sno NOT IN (SELECT sno FROM sc
WHERE cno='c002'
GROUP BY sno)

-- 将两个表连起来
SELECT * FROM (SELECT DISTINCT sno FROM sc
WHERE sno NOT IN (SELECT sno FROM sc
WHERE cno='c002'
GROUP BY sno)) as s2,(SELECT AVG(score)  FROM sc WHERE cno='c002') as s1

-- 添加记录
-- 参考了怎么将一个表插入到另一个表当中:(
-- 如果只希望导入指定字段,可以用这种方法:
-- INSERT INTO 目标表 (`字段1`, `字段2`, ...) SELECT `字段1`, `字段2`, ... FROM 来源表;(这里的话字段必须保持一致)
-- insert into insertTest2(`id`) select `id` from insertTest2;
-- )

INSERT INTO sc(sno,cno,score) SELECT s.sno,'c002',s.a FROM (SELECT * FROM (SELECT DISTINCT sno FROM sc
WHERE sno NOT IN (SELECT sno FROM sc
WHERE cno='c002'
GROUP BY sno)) as s2,(SELECT AVG(score) AS a FROM sc WHERE cno='c002') as s1
) AS s

17、查询各科成绩最高和最低的分:以如下形式显示:课程ID,最高分,最低分

SELECT cno,MAX(score),MIN(score) FROM sc
GROUP BY cno

*18、按各科平均成绩从低到高和及格率的百分数从高到低顺序

select cno,avg(score),(sum(case when score>60 then 1 else 0 end)/COUNT(*))*100 passline
from sc
group by cno
order by  AVG(score) asc,passline desc 

19、查询不同老师所教不同课程平均分从高到低显示

SELECT teacher.tname,AVG(score) FROM sc INNER JOIN (teacher,course) 
ON sc.cno=course.cno AND teacher.tno = course.tno
GROUP BY sc.cno,teacher.tname

*20、统计列印各科成绩,各分数段人数:课程ID,课程名称,[100-85],[85-70],[70-60],[ <60]

SELECT sc.cno,course.cname ,SUM(CASE WHEN score BETWEEN 85 AND 100 THEN 1 ELSE 0 END) AS '[100-85]'
,SUM(CASE WHEN score BETWEEN 70 AND 85 THEN 1 ELSE 0 END) AS '[85-70]'
,SUM(CASE WHEN score BETWEEN 60 AND 70 THEN 1 ELSE 0 END) AS '[70-60]'
,SUM(CASE WHEN score <60 THEN 1 ELSE 0 END) AS '[ <60]'
FROM sc INNER JOIN course ON course.cno=sc.cno
GROUP BY sc.cno,course.cname

*21、查询各科成绩前三名的记录:(不考虑成绩并列情况)

select a.cno,a.first_score, b.second_score from (select cno,max( score)(select s.cno ,max(s.score) second_score from sc s,
( select cno,max ( score) first_score from sc group by cno) awhere s.cno = a.cno
and s.score < a.first_scoregroup by s.cno) b
where a.cno = b.cno

22、查询每门课程被选修的学生数

SELECT course.cname,COUNT(sno) FROM sc INNER JOIN course ON sc.cno=course.cno
GROUP BY sc.cno,course.cname

23、查询出只选修了一门课程的全部学生的学号和姓名

SELECT student.sno,student.sname FROM student INNER JOIN sc ON student.sno=sc.sno
GROUP BY sno
HAVING COUNT(cno)=1

24、查询男生、女生人数

SELECT ssex,COUNT(ssex) FROM student
GROUP BY ssex
HAVING COUNT(ssex)

25、查询姓“张”的学生名单

SELECT * FROM student
WHERE sname LIKE '张%'

26、查询同名同性学生名单,并统计同名人数

SELECT *,(SELECT COUNT(s1.sno) 
FROM student AS s1 INNER JOIN student AS s2 ON s1.sname=s2.sname AND s1.ssex=s2.ssex AND s1.sno!=s2.sno) AS '同名人数' FROM student AS s1 
INNER JOIN student AS s2 ON s1.sname=s2.sname AND s1.ssex=s2.ssex AND s1.sno!=s2.sno

27、1981 年出生的学生名单(注:Student 表中Sage 列的类型是int)

select * from student where student.sage = (SELECT DATE_FORMAT(NOW(), '%Y')-1981)

28、查询每门课程的平均成绩,结果按平均成绩升序排列,平均成绩相同时,按课程号降序排列

SELECT AVG(score) FROM sc
GROUP BY cno
ORDER BY AVG(score) ASC,cno DESC

29、查询平均成绩大于85 的所有学生的学号、姓名和平均成绩

SELECT student.sno,student.sname,AVG(score) FROM student INNER JOIN sc ON student.sno=sc.sno
GROUP BY student.sno,student.sname
HAVING AVG(score)>85

30、查询课程名称为“数据库”,且分数低于60 的学生姓名和分数

SELECT sname,score FROM student INNER JOIN (sc,course) ON student.sno=sc.sno AND course.cno=sc.cno

WHERE (cname='Oracle' OR cname='SQL SERVER 2005') AND score<60

31、查询所有学生的选课情况;

SELECT student.*,sc.cno FROM student LEFT JOIN sc on student.sno=sc.sno

32、查询任何一门课程成绩在70 分以上的姓名、课程名称和分数;

SELECT student.sname,course.cname,sc.score FROM student INNER JOIN (course,sc) 
ON student.sno=sc.sno AND course.cno=sc.cno
WHERE score>70

33、查询不及格的课程,并按课程号从大到小排列

SELECT course.cname,course.cno,sc.score,sc.sno FROM course INNER JOIN sc ON course.cno=sc.cno
WHERE sc.score<60
ORDER BY course.cno DESC

34、查询课程编号为c001 且课程成绩在80 分以上的学生的学号和姓名;

SELECT student.sno,student.sname,sc.score FROM student INNER JOIN sc ON student.sno=sc.sno
WHERE cno='c001' AND score>=80

35、求选了课程的学生人数

SELECT COUNT(DISTINCT sno) FROM sc

36、查询选修“谌燕”老师所授课程的学生中,成绩最高的学生姓名及其成绩

SELECT student.sname,sc.score FROM sc INNER JOIN student ON student.sno=sc.sno
WHERE sc.cno IN (SELECT course.cno FROM teacher INNER JOIN course ON teacher.tno=course.tno
WHERE tname='谌燕')
ORDER BY score DESC
LIMIT 1

37、查询各个课程及相应的选修人数

SELECT course.cno,course.cname,COUNT(sno) FROM course INNER JOIN sc ON sc.cno=course.cno
GROUP BY course.cno,course.cname
HAVING COUNT(sno)

*38、查询不同课程成绩相同的学生的学号、课程号、学生成绩

SELECT s1.sno,s1.cno,s1.score FROM sc AS s1 INNER JOIN sc AS s2 ON s1.sno=s2.sno
WHERE s1.score =s2.score AND s1.cno!=s2.cno

*39、查询每门功课成绩最好的前两名

select s1.* from sc s1 where (select count(1) from sc s2 where s1.cno=s2.cno  and s2.score>=s1.score) <=2 ORDER BY s1.score desc;

40、统计每门课程的学生选修人数(超过10 人的课程才统计)。要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列

SELECT cno,COUNT(sno) FROM sc
GROUP BY cno
HAVING COUNT(sno)>10
ORDER BY COUNT(sno) DESC,cno ASC

41、检索至少选修两门课程的学生学号

SELECT sno FROM sc
GROUP BY sno
HAVING COUNT(cno)>=2

*42、查询全部学生都选修的课程的课程号和课程名

SELECT course.cno,course.cname FROM student INNER JOIN (course,sc) ON student.sno=sc.sno AND sc.cno=course.cno
GROUP BY course.cno,course.cname
HAVING COUNT(*)=(SELECT COUNT(*) FROM student)

43、查询没学过“谌燕”老师讲授的任一门课程的学生姓名

SELECT DISTINCTsname FROM student INNER JOIN sc
WHERE sc.cno NOT IN (SELECT cno FROM course INNER JOIN teacher ON teacher.tno=course.tno
WHERE tname='谌燕')

*44、查询两门以上不及格课程的同学的学号及其平均成绩

select sno ,avg(sc.score)  from sc  GROUP BY sno having count(case when sc.score<60 then 1 else null end)>=2

*45、检索“c004”课程分数小于60,按分数降序排列的同学学号

select * from sc where sc.cno='c004' and sc.score<60 ORDER BY sc.score asc;

*46、删除“s002”同学的“c001”课程的成绩

delete from sc where sc.sno='s002' and sc.cno='c001'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值