数据分析 | MySQL45道练习题(10~18)

题目总览

10.查询没学过[张三]老师讲授的任一门课程的学生姓名

11.查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩

12.检索01课程分数小于60,按分数降序排列的学生信息

13.按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩1

14.查询各科成绩最高分、最低分和平均分

15.按各科成绩进行排名,并显示排名,score重复时继续排序

16.查询学生的总成绩,并进行排名,总分重复时保留名次空缺

17.统计各科成绩分数段人数,课程编号,课程名称,[100-85][85-70][70-60][60-0]及所占百分比

18.查询各科成绩前三名的记录

10.查询没学过[张三]老师讲授的任一门课程的学生姓名

-- 1.先查询出选修了张三老师讲授课程的sid -- 
SELECT s.sid
FROM  teacher t
LEFT JOIN course c
ON t.tid = c.tid
LEFT JOIN sc
ON c.cid = sc.cid
LEFT JOIN student s
ON sc.sid = s.sid
WHERE tname = "张三";
-- 2.与学生表student关联,筛选出不在以上结果内的sid --
SELECT s.*
FROM student s
WHERE sid NOT IN (SELECT s.sid
				  FROM  teacher t
				  LEFT JOIN course c
				  ON t.tid = c.tid
				  LEFT JOIN sc
				  ON c.cid = sc.cid
				  LEFT JOIN student s
				  ON sc.sid = s.sid
				  WHERE tname = "张三");

11.查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩

select a.sid,b.sname,avg(a.score) as avg_score
from sc a
left join student b
on a.sid = b.sid
where a.score < 60
group by a.sid
having count(a.cid) >= 2;

12.检索01课程分数小于60,按分数降序排列的学生信息

-- 筛选出01课程分数小于60分的学生id和分数 --
select sid,score
from sc
where score < 60 and cid = '01';

-- 与student表关联,筛选出学生信息 --
select b.*,a.score
from (select sid,score
from sc
where score < 60 and cid = '01') a
left join student b
on a.sid = b.sid
order by score desc;

13.按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩

-- 1.先从成绩表中筛选出sid和平均成绩 -- 
SELECT sid,AVG(score) avg_score
FROM sc
GROUP BY sid;

-- 2.再用成绩表sc与以上结果进行关联,筛选出sc的所有信息和avg_score --
SELECT sc.*,a.avg_score
FROM sc
LEFT JOIN(SELECT sid,AVG(score) avg_score
          FROM sc
          GROUP BY sid) a
ON sc.sid = a.sid;

-- 3.用以上结果与学生表student进行关联 --
SELECT a.sid,a.score,a.avg_score,s.sname
FROM (SELECT sc.*,a.avg_score
      FROM sc
      LEFT JOIN(SELECT sid,AVG(score) avg_score
                FROM sc
                GROUP BY sid) a
      ON sc.sid = a.sid) a
LEFT JOIN student s
ON a.sid = s.sid
ORDER BY avg_score DESC;

14.查询各科成绩最高分、最低分和平均分
【分析】以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率,中等率,
优良率,优秀率 及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90。要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列

SELECT MIN(score) min_score
			,MAX(score) max_score
			,AVG(score) avg_score
			,COUNT(1) stu_number
			,SUM(CASE WHEN score >= 60 THEN 1 ELSE 0 END)/COUNT(1) 及格率
			,SUM(CASE WHEN score >= 70 AND score < 80 THEN 1 ELSE 0 END)/COUNT(1) 中等率
			,SUM(CASE WHEN score >= 80 AND score < 90 THEN 1 ELSE 0 END)/COUNT(1) 优良率
			,SUM(CASE WHEN score >= 90 THEN 1 ELSE 0 END)/COUNT(1) 优秀率
FROM sc
LEFT JOIN course c
ON sc.cid = c.cid 
GROUP BY sc.cid
ORDER BY stu_number DESC ,sc.cid ASC;

15.按各科成绩进行排名,并显示排名,score重复时继续排序

【分析】变量的使用

SELECT sid,
	   cid,
	   score,
	   @rank:=@rank+1 as rk
FROM sc,(SELECT @rank:=0) as t
ORDER BY score DESC;


-- 自定义变量 --
# ① 定义变量 set @a:=2 (@用来标识变量),使用变量select @a
# ② 定义并使用变量 select @b:=4 
# 修改或者重新赋值 select @b:=6

15.1按各科成绩进行排序,并显示排名,score重复时合并名次

# 法一 
SELECT sid,cid,score,
	   CASE WHEN @sco=score THEN @rank
       ELSE @rank:=@rank+1 END rk,
       @sco:=score
FROM sc,(select @rank:=0,@sco:=null) t
ORDER BY score DESC;

# 法二
SELECT sid,cid,score,
	   CASE WHEN @sco=score THEN @rank
            when  @sco:=score THEN @rank:=@rank+1 
       END rk
FROM sc,(select @rank:=0,@sco:=null) t
ORDER BY score DESC;

16.查询学生的总成绩,并进行排名,总分重复时保留名次空缺

-- 1、学生的总成绩 --
SELECT sid,SUM(score) sum_score
FROM sc
GROUP BY sid
ORDER BY sum_score DESC;


-- 2、名次排序 --
SELECT a.*,
		@rank:=IF(@sco=sum_score,' ',@rank+1) rk
FROM (SELECT sid,
			 SUM(score) sum_score
	  FROM sc
	  GROUP BY sid
	  ORDER BY sum_score DESC) a,(select @sco:=null,@rank:=0) b

17.统计各科成绩分数段人数,课程编号,课程名称,[100-85][85-70][70-60][60-0]及所占百分比
【分析】分组统计数据,判断各分数段的人数情况。

SELECT sc.cid 课程编号,c.cname 课程名称,COUNT(1) 选修人数
	   ,CONCAT(ROUND(SUM(CASE WHEN sc.score >=0 AND sc.score <= 60 THEN 1 ELSE 0 END)/COUNT(1),2),'%') AS '(0-60]'
       ,CONCAT(ROUND(SUM(CASE WHEN sc.score >=60 AND sc.score <= 70 THEN 1 ELSE 0 END)/COUNT(1),2),'%') AS '(60-70]'
       ,CONCAT(ROUND(SUM(CASE WHEN sc.score >= 70 AND sc.score <= 85 THEN 1 ELSE 0 END)/COUNT(1),2),'%') AS '(70-85]'
       ,CONCAT(ROUND(SUM(CASE WHEN sc.score >= 85 AND sc.score <= 100 THEN 1 ELSE 0 END)/COUNT(1),2),'%') AS '(85-100]'
FROM sc
LEFT JOIN course c
ON sc.cid = c.cid
GROUP BY sc.cid;

-- concat的作用是将两个字符拼接起来 --

18.查询各科成绩前三名的记录

【分析】前三名转化为若大于此成绩的数量少于3即为前三名 

SELECT a.*,c.cname
FROM sc a
LEFT JOIN course c
ON a.cid = c.cid 
WHERE (SELECT COUNT(1) 
	   FROM sc b
       WHERE b.cid = a.cid AND b.score > a.score) < 3
ORDER BY cid DESC,score DESC;

你可能感兴趣的:(MySQL,数据分析,数据挖掘,1024程序员节)