MYSQL之SQL练习50题
此次针对SQL进行整体练习,将SQL练习50题进行解答。题目的难度各有差异,难度不是按照题目顺序进行的排序。
其中题目有所参考网上答案,对于个别题目的结果差异,可能是个人理解题意的差异不同造成的,答案不一定正确,但记录一下SQL的常用语法操作。
创建数据表,如果同时执行造成创建失败,请删除各个表,进行逐次创建,
为了方便,出生年月日使用的日期类型,分数使用INT(n),其他字段全部设置为VARCHAR(n)
-- 创建学生表 CREATE TABLE Student( StuNum VARCHAR(20), -- 学号 StuName VARCHAR(20),-- 学生姓名 StuBirth DATE, -- 出生年月日 StuSex VARCHAR(20), -- 性别 CONSTRAINT PK_Num PRIMARY KEY(StuNum) -- 设置学号为主键 ); -- 创建教师表 CREATE TABLE Teacher( TchNum VARCHAR(20), -- 教师编号 TchName VARCHAR(20), -- 教师名字 CONSTRAINT PK_Num PRIMARY KEY(TchNum) -- 设置教师编号为主键 ); -- 创建课程表 CREATE TABLE Course( CrNum VARCHAR(20), -- 课程编号 CrName VARCHAR(20), -- 课程名称 TchNum VARCHAR(20), -- 教师编号 CONSTRAINT PK_Num PRIMARY KEY(CrNum) -- 设置课程编号为主键 ); -- 创建成绩表 CREATE TABLE Score( StuNum VARCHAR(20),-- 学号 CrNum VARCHAR(20), -- 课程编号 SrScore INT(3), -- 学科分数 CONSTRAINT PK_StuCrNum PRIMARY KEY(StuNum,CrNum) -- 设置学号、课程编号为联合主键 );
导入数据,使用插入语句进行数据的导入
-- 插入学生表测试数据 insert into Student values('2019001' , '赵雷' , '1990-01-01' , '男'); insert into Student values('2019002' , '钱电' , '1990-12-21' , '男'); insert into Student values('2019003' , '孙风' , '1990-05-20' , '男'); insert into Student values('2019004' , '李云' , '1990-08-06' , '男'); insert into Student values('2019005' , '周梅' , '1991-12-01' , '女'); insert into Student values('2019006' , '吴兰' , '1992-03-01' , '女'); insert into Student values('2019007' , '郑竹' , '1989-07-01' , '女'); insert into Student values('2019008' , '王菊' , '1990-01-20' , '女'); -- 教师表测试数据 insert into Teacher values('1001' , '张三'); insert into Teacher values('1002' , '李四'); insert into Teacher values('1003' , '王五'); -- 课程表测试数据 insert into Course values('101' , '语文' , '1002'); insert into Course values('102' , '数学' , '1001'); insert into Course values('103' , '英语' , '1003'); -- 成绩表测试数据 insert into Score values('2019001' , '101' , 80); insert into Score values('2019001' , '102' , 90); insert into Score values('2019001' , '103' , 99); insert into Score values('2019002' , '101' , 70); insert into Score values('2019002' , '102' , 60); insert into Score values('2019002' , '103' , 80); insert into Score values('2019003' , '101' , 80); insert into Score values('2019003' , '102' , 80); insert into Score values('2019003' , '103' , 80); insert into Score values('2019004' , '101' , 50); insert into Score values('2019004' , '102' , 30); insert into Score values('2019004' , '103' , 20); insert into Score values('2019005' , '101' , 76); insert into Score values('2019005' , '102' , 87); insert into Score values('2019006' , '101' , 31); insert into Score values('2019006' , '103' , 34); insert into Score values('2019007' , '102' , 89); insert into Score values('2019007' , '103' , 98);
SQL的50练习题详解
-- 做题于2019-11-19 -- 学生表 select * from student; -- 教师表 select * from teacher; -- 课程表 select * from course; -- 成绩表 select * from score; -- 1、查询"101"课程比"102"课程成绩高的学生的信息及课程分数 SELECT student.StuNum, StuName, StuBirth, StuSex, course.CrName, SrScore FROM student LEFT JOIN score ON student.StuNum = score.StuNum LEFT JOIN course ON score.CrNum = course.CrNum WHERE student.StuNum IN( SELECT a.StuNum FROM (SELECT StuNum, SrScore AS a_score FROM score WHERE CrNum = '101') a INNER JOIN (SELECT StuNum, SrScore AS b_score FROM score WHERE CrNum = '102') b ON a.StuNum = b.StuNum WHERE a_score > b_score ); -- 2、查询"101"课程比"102"课程成绩低的学生的信息及课程分数 SELECT student.StuNum, StuName, StuBirth, StuSex, course.CrName, SrScore FROM student LEFT JOIN score ON student.StuNum = score.StuNum LEFT JOIN course ON score.CrNum = course.CrNum WHERE student.StuNum IN( SELECT a.StuNum FROM (SELECT StuNum, SrScore AS a_score FROM score WHERE CrNum = '101') a INNER JOIN (SELECT StuNum, SrScore AS b_score FROM score WHERE CrNum = '102') b ON a.StuNum = b.StuNum WHERE a_score < b_score ); -- 3、查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩 SELECT A.StuNum, A.StuName, B.avg_SrScore FROM student A INNER JOIN (SELECT StuNum, AVG(SrScore) AS avg_SrScore FROM score GROUP BY StuNum HAVING AVG(SrScore) >= 60) B ON A.StuNum = B.StuNum; -- 4、查询平均成绩小于60分的同学的学生编号和学生姓名和平均成绩(包括有成绩的和无成绩的) SELECT A.StuNum, A.StuName, B.avg_SrScore FROM student A INNER JOIN (SELECT StuNum, AVG(SrScore) AS avg_SrScore FROM score GROUP BY StuNum HAVING AVG(SrScore) < 60) B ON A.StuNum = B.StuNum; -- 5、查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩 SELECT A.StuNum, A.StuName, B.count_StuNum '选课数', B.sum_SrScore '总成绩' FROM student A RIGHT JOIN ( SELECT StuNum, COUNT(StuNum) count_StuNum, SUM(SrScore) sum_SrScore FROM score GROUP BY StuNum ) B ON A.StuNum = B.StuNum; -- 6、查询"李"姓老师的数量 SELECT COUNT(1) FROM teacher WHERE TchName LIKE '李%'; -- 7、查询学过"张三"老师授课的同学的信息 SELECT StuNum, StuName, StuBirth, StuSex FROM student WHERE StuNum IN( SELECT StuNum FROM score WHERE CrNum = (SELECT CrNum FROM course INNER JOIN teacher ON course.TchNum = teacher.TchNum AND teacher.TchName = '张三') ); -- 8、查询没学过"张三"老师授课的同学的信息 SELECT StuNum, StuName, StuBirth, StuSex FROM student WHERE StuNum NOT IN( SELECT DISTINCT StuNum FROM score WHERE CrNum = (SELECT CrNum FROM course INNER JOIN teacher ON course.TchNum = teacher.TchNum AND teacher.TchName = '张三') ); -- 9、查询学过编号为"101"并且也学过编号为"102"的课程的同学的信息 SELECT StuNum, StuName, StuBirth, StuSex FROM student WHERE StuNum IN(SELECT StuNum FROM score WHERE CrNum = '101') AND StuNum IN(SELECT StuNum FROM score WHERE CrNum = '102'); -- 10、查询学过编号为"101"但是没有学过编号为"102"的课程的同学的信息 SELECT StuNum, StuName, StuBirth, StuSex FROM student WHERE StuNum IN(SELECT StuNum FROM score WHERE CrNum = '101') AND StuNum NOT IN(SELECT StuNum FROM score WHERE CrNum = '102'); -- 11、查询没有学全所有课程的同学的信息 SELECT student.StuNum, StuName, StuBirth, StuSex FROM student LEFT JOIN score ON student.StuNum = score.StuNum GROUP BY StuNum HAVING count(1) < (SELECT count(1) FROM course); -- 12、查询至少有一门课与学号为"2019001"的同学所学相同的同学的信息 SELECT DISTINCT student.StuNum, StuName, StuBirth, StuSex FROM student LEFT JOIN score ON student.StuNum = score.StuNum AND CrNum IN(SELECT CrNum FROM score WHERE StuNum = '2019001'); -- 13、查询和"2019001"号的同学学习的课程完全相同的其他同学的信息 SELECT student.StuNum, StuName, StuBirth, StuSex FROM student LEFT JOIN score ON student.StuNum = score.StuNum GROUP BY student.StuNum HAVING group_concat(score.CrNum) = ( SELECT group_concat(score.CrNum) FROM student LEFT JOIN score ON student.StuNum = score.StuNum WHERE student.StuNum = '2019001'); -- 14、查询没学过"张三"老师讲授的任一门课程的学生姓名 SELECT DISTINCT student.StuNum, StuName, StuBirth, StuSex FROM student WHERE StuNum NOT IN( SELECT StuNum FROM score WHERE CrNum = ( SELECT CrNum FROM teacher INNER JOIN course ON teacher.TchNum = course.TchNum AND teacher.TchName = '张三' ) ); -- 15、查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩 SELECT student.StuNum, student.StuName, avg(SrScore) AS '平均成绩' FROM student LEFT JOIN score ON student.StuNum = score.StuNum WHERE student.StuNum IN(SELECT StuNum FROM score WHERE SrScore < 60 GROUP BY StuNum HAVING count(1) >= 2); -- 16、检索"101"课程分数小于60,按分数降序排列的学生信息 SELECT StuNum, StuName, StuBirth, StuSex FROM student WHERE StuNum IN(SELECT StuNum FROM score WHERE CrNum = '101' AND SrScore < 60); -- 17、按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩 SELECT student.StuNum, MAX(CASE score.CrNum WHEN '101' THEN score.SrScore ELSE 0 END) '语文', MAX(CASE score.CrNum WHEN '102' THEN score.SrScore ELSE 0 END) '数学', MAX(CASE score.CrNum WHEN '103' THEN score.SrScore ELSE 0 END) '英语', AVG(SrScore) AS '平均成绩' FROM student INNER JOIN score ON student.StuNum = score.StuNum GROUP BY score.StuNum ORDER BY AVG(SrScore) DESC; -- 18.查询各科成绩最高分、最低分和平均分:显示形式:课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率 -- 及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90 SELECT course.CrNum, course.CrName, MAX(score.SrScore) '最高分', MIN(score.SrScore) '最低分', ROUND(100*((SELECT count(1) FROM score WHERE score.CrNum = course.CrNum AND SrScore >= 60) /(SELECT count(1) FROM score WHERE score.CrNum = course.CrNum)),2) '及格率', ROUND(100*((SELECT count(1) FROM score WHERE score.CrNum = course.CrNum AND SrScore >= 70 AND SrScore < 80) /(SELECT count(1) FROM score WHERE score.CrNum = course.CrNum)),2) '中等率', ROUND(100*((SELECT count(1) FROM score WHERE score.CrNum = course.CrNum AND SrScore >= 80 AND SrScore < 90) /(SELECT count(1) FROM score WHERE score.CrNum = course.CrNum)),2) '优良率', ROUND(100*((SELECT count(1) FROM score WHERE score.CrNum = course.CrNum AND SrScore >= 90 AND SrScore <= 100) /(SELECT count(1) FROM score WHERE score.CrNum = course.CrNum)),2) '优秀率' FROM course INNER JOIN score ON course.CrNum = score.CrNum GROUP BY course.CrNum; -- 19、按各科成绩进行排序,并显示排名 -- 方式一 select StuNum, CrNum, SrScore, (@rank := @rank + 1) AS rank from (score, (SELECT @rank := 0) b) order by CrNum, SrScore desc; -- 方式二 select * from ( select StuNum, CrNum, SrScore, (@i :=@i + 1) AS rank from ((select StuNum,CrNum,SrScore from score where CrNum = '101' order by SrScore desc) a, (SELECT @i := 0) b) UNION ALL select StuNum, CrNum, SrScore, (@j :=@j + 1) AS rank from ((select StuNum,CrNum,SrScore from score where CrNum = '102' order by SrScore desc) a, (SELECT @j := 0) b) UNION ALL select StuNum, CrNum, SrScore, (@k :=@k + 1) AS rank from ((select StuNum,CrNum,SrScore from score where CrNum = '103' order by SrScore desc) a, (SELECT @k := 0) b) ) T; -- 20、查询学生的总成绩并进行排名 select StuNum, SUM(SrScore) as '总成绩' from score GROUP BY StuNum order by '总成绩' DESC; -- 21、查询不同老师所教不同课程平均分从高到低显示 SELECT teacher.TchName, course.CrNum, course.CrName, AVG(SrScore) '平均分' FROM teacher INNER JOIN course ON teacher.TchNum = course.TchNum RIGHT JOIN score ON course.CrNum = score.CrNum GROUP BY teacher.TchNum ORDER BY AVG(SrScore) DESC; -- 22、查询所有课程的成绩第2名到第3名的学生信息及该课程成绩 SELECT student.StuNum, StuName, StuBirth, StuSex, SrScore FROM student RIGHT JOIN ( (SELECT StuNum,SrScore FROM score WHERE CrNum = '101' ORDER BY SrScore DESC LIMIT 1, 2) UNION ALL (SELECT StuNum,SrScore FROM score WHERE CrNum = '102' ORDER BY SrScore DESC LIMIT 1, 2) UNION ALL (SELECT StuNum,SrScore FROM score WHERE CrNum = '103' ORDER BY SrScore DESC LIMIT 1, 2) ) Sr ON student.StuNum = Sr.StuNum; -- 23、统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[0-60]及所占百分比 SELECT course.CrNum, course.CrName, ((select count(1) from score where score.CrNum = course.CrNum and SrScore >= 85 and SrScore <= 100) /(select count(1) from score where score.CrNum = course.CrNum)) '[85,100]', ((select count(1) from score where score.CrNum = course.CrNum and SrScore >= 70 and SrScore < 85) /(select count(1) from score where score.CrNum = course.CrNum)) '[70,85]', ((select count(1) from score where score.CrNum = course.CrNum and SrScore >= 60 and SrScore < 70) /(select count(1) from score where score.CrNum = course.CrNum)) '[60,70]', ((select count(1) from score where score.CrNum = course.CrNum and SrScore < 60) /(select count(1) from score where score.CrNum = course.CrNum)) '[0,60]' FROM course INNER JOIN score ON course.CrNum = score.CrNum GROUP BY course.CrNum; -- 24、查询学生平均成绩及其名次 SELECT StuNum, avg_SrScore '平均分', (@rank := @rank + 1) '排名' FROM ((SELECT StuNum, AVG(SrScore) avg_SrScore FROM score GROUP BY StuNum ORDER BY AVG(SrScore) DESC) a, (SELECT @rank := 0) b ); -- 25、查询各科成绩前三名的记录 select * from ( (select * from score where CrNum = '101' order by SrScore desc LIMIT 3) UNION (select * from score where CrNum = '102' order by SrScore desc LIMIT 3) UNION (select * from score where CrNum = '103' order by SrScore desc LIMIT 3) ) T; -- 26、查询每门课程被选修的学生数 SELECT course.CrNum, course.CrName, count(1) FROM course INNER JOIN score ON course.CrNum = score.CrNum GROUP BY CrNum; -- 27、查询出只有两门课程的全部学生的学号和姓名 SELECT StuNum, StuName FROM student WHERE StuNum IN (SELECT StuNum FROM score GROUP BY StuNum HAVING count(1) = 2); -- 28、查询男生、女生人数 SELECT StuSex, count(1) FROM student GROUP BY StuSex; -- 29、查询名字中含有"风"字的学生信息 SELECT StuNum,StuName,StuBirth,StuSex FROM student where StuName like '%风%'; -- 30、查询同名同姓学生名单,并统计同名人数 SELECT StuName, count(1) FROM student group by StuName having count(1) > 1; -- 31、查询1990年出生的学生名单 SELECT StuNum,StuName,StuBirth,StuSex FROM student WHERE YEAR(StuBirth) = '1990'; -- 32、查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号 SELECT CrNum, AVG(SrScore) '平均成绩' FROM score GROUP BY CrNum ORDER BY AVG(SrScore) DESC, CrNum; -- 33、查询平均成绩大于等于85的所有学生的学号、姓名和平均成绩 SELECT student.StuNum, student.StuName, AVG(SrScore) '平均成绩' FROM student INNER JOIN score ON student.StuNum = score.StuNum GROUP BY student.StuNum HAVING AVG(SrScore) >= 85; -- 34、查询课程名称为"数学",且分数低于60的学生姓名和分数 SELECT StuName, SrScore FROM student INNER JOIN score ON student.StuNum = score.StuNum AND SrScore < 60 INNER JOIN course ON score.crnum = course.CrNum AND CrName = '数学'; -- 35、查询所有学生的课程及分数情况 SELECT student.StuNum, StuName, course.CrNum, CrName, SrScore FROM student INNER JOIN score ON student.StuNum = score.StuNum INNER JOIN course ON score.crnum = course.CrNum; -- 36、查询任何一门课程成绩在70分以上的姓名、课程名称和分数 SELECT StuName, CrName, SrScore FROM student INNER JOIN score ON student.StuNum = score.StuNum AND SrScore >= 70 INNER JOIN course ON score.crnum = course.CrNum; SELECT StuName, MAX(case course.CrName WHEN '语文' THEN SrScore ELSE 0 END) '语文', MAX(case course.CrName WHEN '数学' THEN SrScore ELSE 0 END) '数学', MAX(case course.CrName WHEN '英语' THEN SrScore ELSE 0 END) '英语' FROM student INNER JOIN score ON student.StuNum = score.StuNum AND SrScore >= 70 INNER JOIN course ON score.CrNum = course.CrNum GROUP BY StuName; -- 37、查询不及格的课程 SELECT StuName, CrName, SrScore FROM student INNER JOIN score ON student.StuNum = score.StuNum AND SrScore < 60 INNER JOIN course ON score.CrNum = course.CrNum; -- 38、查询课程编号为"101"且课程成绩在80分以上的学生的学号和姓名 SELECT student.StuNum, StuName, SrScore FROM student INNER JOIN score ON student.StuNum = score.StuNum AND SrScore >= 80 AND CrNum = '101'; -- 39、求每门课程的学生人数 SELECT course.CrNum, CrName, count(1) FROM course INNER JOIN score ON course.CrNum = score.CrNum GROUP BY course.CrNum; -- 40、查询选修"张三"老师所授课程的学生中,成绩最高的学生信息及其成绩 SELECT student.StuNum, StuName, StuBirth, StuSex, SrScore FROM student INNER JOIN score ON student.StuNum = score.StuNum INNER JOIN course ON score.CrNum = course.CrNum INNER JOIN teacher ON course.TchNum = teacher.TchNum AND TchName = '张三' ORDER BY SrScore DESC LIMIT 1; -- 41、查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩 -- 个人理解:指同一个学生的不同学科,但考试成绩相同的数据 SELECT DISTINCT a.StuNum, a.CrNum, a.SrScore FROM (SELECT StuNum, CrNum, SrScore FROM score) a INNER JOIN (SELECT StuNum, CrNum, SrScore FROM score) b ON a.StuNum = b.StuNum AND a.CrNum != b.CrNum AND a.SrScore = b.SrScore; -- 42、查询每门功课成绩最好的前两名 -- 方式一 select * from ( (select * from score where CrNum = '101' order by SrScore desc LIMIT 2) UNION (select * from score where CrNum = '102' order by SrScore desc LIMIT 2) UNION (select * from score where CrNum = '103' order by SrScore desc LIMIT 2) ) T; -- 方式二 更具有普适性 SELECT StuNum, CrNum, SrScore FROM score a WHERE (SELECT COUNT(1) FROM score b WHERE b.CrNum = a.CrNum AND b.SrScore >= a.SrScore) <= 2 ORDER BY a.CrNum; -- 43、统计每门课程的学生选修人数(超过5人的课程才统计), -- 要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列 SELECT CrNum, count(1) FROM score GROUP BY CrNum HAVING count(1) > 5 ORDER BY count(1) DESC, CrNum ASC; -- 44、检索至少选修两门课程的学生学号 select StuNum from score group by StuNum having COUNT(1) >= 2; -- 45、查询选修了全部课程的学生信息 SELECT StuNum FROM score GROUP BY StuNum HAVING COUNT(1) = (SELECT count(1) FROM course); -- 46、查询各学生的年龄 SELECT (YEAR(NOW())-YEAR(StuBirth)) '年龄' FROM student; -- 47、查询本周过生日的学生 SELECT StuNum,StuName,StuBirth,StuSex FROM student WHERE WEEK(StuBirth)=WEEK(NOW()); -- 48、查询下周过生日的学生 SELECT StuNum,StuName,StuBirth,StuSex FROM student WHERE WEEK(StuBirth)= (WEEK(NOW()) + 1); -- 49、查询本月过生日的学生 SELECT StuNum,StuName,StuBirth,StuSex FROM student WHERE MONTH(StuBirth)= MONTH(NOW()); -- 50、查询下月过生日的学生 SELECT StuNum,StuName,StuBirth,StuSex FROM student WHERE MONTH(StuBirth)= (MONTH(NOW()) + 1);

浙公网安备 33010602011771号