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'