原文链接
网上找来SQL50道练习题,逐个练习,做一记录。
1.学生表
student(sid,sname,sage,ssex)
学生编号,学生姓名, 出生年月,学生性别
2.课程表
course(cid,cname,tid)
课程编号, 课程名称, 教师编号
3.教师表
teacher(tid,tname)
教师编号,教师姓名
4.成绩表
sc(sid,cid,score)
学生编号,课程编号,分数
1、查询"01"课程比"02"课程成绩高的学生的信息及课程分数
SELECT a.aid,a.ascore,b.bscore FROM
(SELECT sc.sid aid,sc.score ascore FROM sc WHERE CId = 01)a
INNER JOIN
(SELECT sc.SId bid,sc.score bscore FROM sc WHERE CId = 02)b
ON a.aid = b.bid
WHERE a.ascore > b.bscore
或者 null值按0算
SELECT a.aid,a.ascore,c.cscore FROM
(SELECT sc.sid aid,sc.score ascore FROM sc WHERE CId = 01)a
LEFT JOIN
(
SELECT student.sid cid, IFNULL(b.bscore,0) cscore FROM student
LEFT JOIN (SELECT sc.sid bid ,sc.cid,sc.score bscore FROM sc WHERE CId = 02)b
ON b.bid = student.SId
)c
ON a.aid = c.cid
WHERE a.ascore > c.cscore
2、查询"01"课程比"02"课程成绩低的学生的信息及课程分数
SELECT a.aid,a.ascore,b.bscore FROM
(SELECT sc.sid aid,sc.score ascore FROM sc WHERE CId = 01)a
INNER JOIN
(SELECT sc.SId bid,sc.score bscore FROM sc WHERE CId = 02)b
ON a.aid = b.bid
WHERE a.ascore < b.bscore
3、查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩
SELECT student.*,AVG(sc.score) avg FROM student
JOIN sc ON sc.SId = student.SId
GROUP BY sc.SId
HAVING avg < 60
4、查询平均成绩小于60分的同学的学生编号和学生姓名和平均成绩(包括有成绩的和无成绩的)
=========Having 后附加条件=========
SELECT student.*,AVG(sc.score) FROM student
LEFT JOIN sc ON sc.SId = student.SId
GROUP BY student.SId
HAVING AVG(sc.score) < 60 OR ISNULL(AVG(sc.score))
5、查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩
SELECT student.*,COUNT(sc.CId),SUM(sc.score) FROM student
LEFT JOIN sc ON sc.SId = student.SId
GROUP BY student.SId
6、查询"李"姓老师的数量
SELECT COUNT(*) FROM teacher WHERE Tname LIKE '李%'
7、查询学过"张三"老师授课的同学的信息
SELECT student.* FROM sc
RIGHT JOIN student ON sc.SId = student.SId
RIGHT JOIN course ON course.CId = sc.CId
RIGHT JOIN teacher ON teacher.TId = course.TId
WHERE teacher.Tname = '张三'
8、查询没学过"张三"老师授课的同学的信息
SELECT student.* FROM student
WHERE SId NOT IN
(
SELECT student.SId FROM sc
RIGHT JOIN student ON sc.SId = student.SId
RIGHT JOIN course ON course.CId = sc.CId
RIGHT JOIN teacher ON teacher.TId = course.TId
WHERE teacher.Tname = '张三'
)
9、查询学过编号为"01"并且也学过编号为"02"的课程的同学的信息
SELECT student.* FROM sc
LEFT JOIN student ON student.SId = sc.SId
WHERE CId = 01
AND sc.SId IN (SELECT sc.SId FROM sc WHERE CId = 02)
10、查询学过编号为"01"但是没有学过编号为"02"的课程的同学的信息
SELECT student.* FROM sc
LEFT JOIN student ON student.SId = sc.SId
WHERE CId = 01
AND sc.SId NOT IN (SELECT sc.SId FROM sc WHERE CId = 02)
11、查询没有学全所有课程的同学的信息
SELECT student.*,COUNT(sc.CId) co FROM student
RIGHT JOIN sc ON sc.SId = student.SId
GROUP BY SId
HAVING co < (SELECT COUNT(*) FROM course)
12、查询至少有一门课与学号为"01"的同学所学相同的同学的信息
SELECT DISTINCT a.sid,student.Sname FROM sc a
LEFT JOIN student
ON student.SId = a.SId
WHERE a.CId IN (SELECT DISTINCT sc.cid FROM sc WHERE sc.SId = 01)
AND a.SId != 01
13、查询和"01"号的同学学习的课程完全相同的其他同学的信息
14、查询没学过"张三"老师讲授的任一门课程的学生姓名
SELECT student.* FROM student WHERE SId NOT IN
(
SELECT student.SId FROM teacher
RIGHT JOIN course ON course.TId = teacher.TId
RIGHT JOIN sc ON sc.CId = course.CId
RIGHT JOIN student ON student.SId = sc.SId
WHERE teacher.Tname = '张三'
)
15、查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
SELECT sc.SId,student.Sname,
SUM(CASE WHEN score < 60 THEN 1 ELSE 0 END ) AS co
FROM sc
LEFT JOIN student ON student.SId = sc.SId
GROUP BY sc.SId
HAVING co > 1
16、检索"01"课程分数小于60,按分数降序排列的学生信息
SELECT student.* ,sc.cid,course.Cname,sc.score FROM student
RIGHT JOIN sc ON sc.SId = student.SId
RIGHT JOIN course ON sc.CId = course.CId
WHERE sc.CId =01
AND score < 60
17、按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
SELECT sc.SId, round(AVG(sc.score),2) avg,
SUM(CASE WHEN CId = 01 THEN score ELSE 0 END) AS '01',
SUM(CASE WHEN CId = 02 THEN score ELSE 0 END) AS '02',
SUM(CASE WHEN CId = 03 THEN score ELSE 0 END) AS '03'
FROM sc
GROUP BY sid
ORDER BY avg
18.查询各科成绩最高分、最低分和平均分:以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率
--及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90
SELECT sc.CId,course.Cname,
MAX(sc.score) '最高分',
MIN(sc.score) '最低分',
AVG(sc.score) '平均分',
ROUND(SUM(CASE WHEN score >= 90 THEN 1 ELSE 0 END )/COUNT(*) * 100,2) '优率',
ROUND(SUM(CASE WHEN score >= 80 AND score < 90 THEN 1 ELSE 0 END)/COUNT(*)* 100,2) '良率',
ROUND(SUM(CASE WHEN score >= 70 AND score < 80 THEN 1 ELSE 0 END)/COUNT(*)*100,2) '中率',
ROUND(SUM(CASE WHEN score >= 60 AND score < 70 THEN 1 ELSE 0 END)/COUNT(*)*100,2) '及格率'
FROM sc
LEFT JOIN course
ON course.CId = sc.CId
GROUP BY sc.CId
20、查询学生的总成绩并进行排名
SELECT a.sid,
@i := @i+1 as i,
@k := (CASE WHEN @score = a.sum THEN @k ELSE @i END) as rank,
@score := a.sum as score
FROM
(
SELECT sc.sid,SUM(sc.score) sum, ROUND(AVG(sc.score),2) avg FROM sc
GROUP BY sc.SId
ORDER BY avg DESC
)a,
(SELECT @k:=0, @i:=0,@score :=0)b
21、查询不同老师所教不同课程平均分从高到低显示
SELECT teacher.Tname,course.Cname,AVG(sc.score)
FROM teacher
LEFT JOIN course ON teacher.TId = course.TId
LEFT JOIN sc ON sc.CId = course.CId
GROUP BY sc.CId
ORDER BY AVG(sc.score)
22、查询所有课程的成绩第2名到第3名的学生信息及该课程成绩
23、统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[0-60]及所占百分比
SELECT sc.CId,course.Cname,
SUM(CASE WHEN score >= 85 THEN 1 ELSE 0 END )AS '85-100',
ROUND(SUM(CASE WHEN score >= 85 THEN 1 ELSE 0 END )/COUNT(*) * 100,2) 'per1',
SUM(CASE WHEN score >= 70 AND score < 85 THEN 1 ELSE 0 END) AS '70-85',
ROUND(SUM(CASE WHEN score >= 70 AND score < 85 THEN 1 ELSE 0 END)/COUNT(*)* 100,2) 'per2',
SUM(CASE WHEN score >= 60 AND score < 70 THEN 1 ELSE 0 END) AS '60-70',
ROUND(SUM(CASE WHEN score >= 60 AND score < 70 THEN 1 ELSE 0 END)/COUNT(*)*100,2) 'per3',
SUM(CASE WHEN score < 60 THEN 1 ELSE 0 END) AS '0-60',
ROUND(SUM(CASE WHEN score < 60 THEN 1 ELSE 0 END)/COUNT(*)*100,2) 'per4'
FROM sc
LEFT JOIN course
ON course.CId = sc.CId
GROUP BY sc.cid
24、查询学生平均成绩及其名次(变量的使用)
SELECT a.sid,
@i:=@i+1 AS '不保留空缺排名',
@k:=(case when @avg_score=a.avg_s then @k else @i end) AS '保留空缺排名',
@avg_score:=avg_s AS '平均分'
FROM
(
select sid, ROUND(AVG(score),2) AS avg_s
from sc
GROUP BY sid
ORDER BY avg_s DESC
)a,
(select @avg_score:=0,@i:=0,@k:=0)b;
25、查询各科成绩前三名的记录(同42)
SELECT a.sid,a.cid,a.score,b.sid,b.cid,b.score FROM sc a
LEFT JOIN sc b
ON a.CId = b.CId AND a.score < b.score
GROUP BY a.SId,a.CId,a.score
HAVING COUNT(b.SId) < 3
ORDER BY a.CId,a.score DESC
26、查询每门课程被选修的学生数
SELECT sc.cid,course.Cname,COUNT(sc.sid) FROM sc
LEFT JOIN course
ON sc.CId = course.CId
GROUP BY sc.cId
27、查询出只有两门课程的全部学生的学号和姓名
SELECT sc.SId ,COUNT(sc.CId) co FROM sc
LEFT JOIN student
ON student.SId = sc.SId
GROUP BY SId
HAVING co = 2
28、查询男生、女生人数
SELECT Ssex,COUNT(Ssex) FROM student GROUP BY Ssex
29、查询名字中含有"风"字的学生信息
SELECT * FROM student WHERE Sname LIKE '%风%'
30、查询同名同性学生名单,并统计同名人数
SELECT Sname,COUNT(*) FROM student GROUP BY Sname HAVING COUNT(*) > 1
31、查询1990年出生的学生名单
SELECT student.* FROM student WHERE YEAR(Sage) = 1990
或者
SELECT student.* FROM student WHERE Sage LIKE '1990%'
32、查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
SELECT course.CId,course.Cname,AVG(sc.score)
FROM sc
LEFT JOIN course
ON course.CId = sc.CId
GROUP BY CId
ORDER BY AVG(sc.score) DESC, course.CId
33、查询平均成绩大于等于85的所有学生的学号、姓名和平均成绩
SELECT student.* FROM student
WHERE SId IN
(
SELECT sid FROM sc
GROUP BY SId
HAVING AVG(score) > 85
)
34、查询课程名称为"数学",且分数低于60的学生姓名和分数
SELECT student.sid,student.Sname,sc.score,course.CId,course.Cname
FROM student
LEFT JOIN sc ON sc.SId = student.SId
LEFT JOIN course ON sc.CId = course.CId
WHERE course.Cname = '数学'
AND score < 60
35、查询所有学生的课程及分数情况;
SELECT student.sid,student.Sname,
sum(case WHEN course.Cname = '语文' THEN sc.score ELSE 0 END ) AS '语文',
sum(case WHEN course.Cname = '数学' THEN sc.score ELSE 0 END ) AS '数学',
sum(case WHEN course.Cname = '英语' THEN sc.score ELSE 0 END ) AS '英语',
sum( sc.score ) AS '总分'
FROM student
LEFT JOIN sc on sc.sid = student.SId
LEFT JOIN course on course.cid = sc.CId
GROUP BY SId
36、查询任何一门课程成绩在70分以上的姓名、课程名称和分数
SELECT student.* FROM student
RIGHT JOIN
(
SELECT sid ,MAX(score) FROM sc
GROUP BY SId
HAVING MAX(score) > 70
) t1
ON t1.sid = student.SId
37、查询不及格的课程
SELECT course.cid,course.Cname FROM course
RIGHT JOIN
(
SELECT cid tid FROM sc
WHERE score < 60
GROUP BY CId
)t1
ON t1.tid = course.CId
38、查询课程编号为01且课程成绩在80分以上的学生的学号和姓名;
SELECT student.* ,sc.score FROM student,course,sc
WHERE student.sid = sc.SId
AND sc.CId = course.CId
AND course.CId = 01
AND sc.score > 70
或者:
SELECT student.* ,sc.score FROM sc
LEFT JOIN student
ON sc.SId = student.SId
WHERE sc.cId = 01
AND sc.score > 70
39、求每门课程的学生人数
SELECT cid,COUNT(sid) FROM sc
GROUP BY CId
40、查询选修"张三"老师所授课程的学生中,成绩最高的学生信息及其成绩,假定只有一个最高分
select student.*, sc.score, sc.cid from student, teacher, course,sc
where teacher.tid = course.tid
and sc.sid = student.sid
and sc.cid = course.cid
and teacher.tname = "张三"
order by score desc
limit 1;
41、查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩
SELECT DISTINCT a.sid,a.cid,a.score FROM sc a
LEFT JOIN sc b
ON a.CId != b.CId AND a.score = b.score
42、查询每门功成绩最好的前两名
select a.sid,a.cid,a.score from sc a
where (select COUNT(*) from sc b where b.cid=a.cid and b.score>=a.score)<=2
ORDER BY a.cid
43、统计每门课程的学生选修人数(超过5人的课程才统计)。
要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
SELECT cid,COUNT(sid) per FROM sc
GROUP BY CId
HAVING COUNT(sid) >= 5
ORDER BY per desc,cid;
44、检索至少选修两门课程的学生学号
SELECT sid,COUNT(CId) FROM sc
GROUP BY SId
HAVING COUNT(CId) >=2
45、查询选修了全部课程的学生信息
SELECT * FROM student WHERE
SId IN
(
SELECT sid FROM sc
GROUP BY SId
HAVING COUNT(CId) = (SELECT COUNT(*) FROM course)
)
46、查询各学生的年龄
SELECT student.sid, student.Sname,TIMESTAMPDIFF(YEAR,Sage,NOW())
from student
47、查询本周过生日的学生
SELECT * from student WHERE WEEKOFYEAR(Sage) = WEEKOFYEAR(NOW())
48、查询下周过生日的学生
SELECT * from student WHERE WEEKOFYEAR(Sage) = WEEKOFYEAR(NOW())+1
49、查询本月过生日的学生
SELECT * FROM student WHERE MONTH(Sage) = MONTH(now())
50、查询下月过生日的学生
SELECT * FROM student WHERE MONTH(sage) = MONTH(NOW())+1