(自连接、子查询、多表联查、窗口函数) MySQL经典45题重难点复习

MySQL经典45题中难度题型复习

经典45题涉及数据表如下
student表:
在这里插入图片描述
sc表:
在这里插入图片描述
course表:
在这里插入图片描述
teacher表:
在这里插入图片描述
注:题目难度等级因人而异,以下关于中、难的分级也是练习时根据自己的状况划分的。以下题目多涉及子链接、自连接、多表连接等重难点,值得反复思考

自连接

-- (中)1.查询" 01 "课程比" 02 "课程成绩高的学生的信息及课程分数
SELECT*FROM sc a LEFT JOIN student b on a.sid=b.sid
INNER JOIN sc c ON a.sid=c.sid AND a.cid=01 AND c.cid=02
WHERE a.score > c.score
-- 1.1 查询同时存在" 01 "课程和" 02 "课程的情况
SELECT * FROM sc a INNER JOIN sc b ON a.sid=b.sid
WHERE a.cid=01 AND b.cid=02
-- 1.2 查询存在" 01 "课程但可能不存在" 02 "课程的情况(不存在时显示为 null) 
SELECT*FROM sc a LEFT JOIN sc b ON a.sid=b.sid AND b.cid=02
WHERE a.cid=01 
-- 1.3 查询不存在" 01 "课程但存在" 02 "课程的情况
SELECT * FROM (SELECT * FROM sc WHERE sid 
NOT IN (SELECT sid FROM sc WHERE cid=01)) a
INNER JOIN sc b
on a.sid=b.sid AND b.cid=02

子查询与多表联查

-- (中)7.查询没有学全所有课程的同学的信息
SELECT b.*,COUNT(CId) FROM sc a 
INNER JOIN student b ON a.sid=b.SId
group by sid
HAVING count(cid) < (SELECT count(cid) FROM course)
-- (中)39.查询选修了全部课程的学生信息
SELECT b.*,count(cid) FROM sc a
INNER JOIN student b on a.sid=b.sid
GROUP BY sid 
HAVING count(cid)=(SELECT count(cid) FROM course) 
-- (中)8.查询至少有一门课与学号为" 01 "的同学所学相同的同学的信息
SELECT b.* FROM sc a INNER JOIN student b on a.sid=b.sid
where a.cid IN (SELECT cid FROM sc WHERE sid=01)
GROUP BY a.sid
-- (难)9.查询和" 01 "号的同学学习的课程 完全相同的其他同学的信息
SELECT c.* FROM student c 
       INNER JOIN 
            (SELECT sid,GROUP_CONCAT(CId order by CId asc) as courses 
            FROM sc GROUP BY SId) a
       INNER JOIN
            (SELECT sid,GROUP_CONCAT(CId order by CId asc) as courses
             FROM sc GROUP BY SId HAVING sid = 01) b
      ON  a.sid!=01 AND a.courses=b.courses AND a.sid=c.sid
-- (难)10.查询没学过“张三”老师讲授的任一门课程的学生姓名
SELECT *
FROM student where sid NOT IN
(SELECT sid FROM sc c 
LEFT JOIN course b on b.cid=c.cid
INNER JOIN teacher a on a.tid=b.tid where a.tname='张三')
-- (难)11.查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
SELECT b.sid,b.sname,avg(score) FROM sc a 
LEFT JOIN student b ON a.sid=b.sid 
INNER JOIN 
(SELECT sid FROM sc WHERE score<60 GROUP BY sid HAVING count(cid) >=2)c 
on a.sid=c.sid
GROUP BY b.sid

CASE WHEN

-- (中)14.查询各科成绩最高分、最低分和平均分: 以如下形式显示:课程 ID,课程 name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率 及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90 要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
SELECT a.cid,b.cname,MAX(a.score) AS '最高分',MIN(a.score) AS '最低分',AVG(a.score) AS '平均分',COUNT(sid) AS '选课人数',
sum(CASE WHEN score>=60 THEN 1 ELSE 0 END)/COUNT(sid) AS '及格率',
sum(CASE WHEN score>=70 AND score<80 THEN 1 ELSE 0 END)/COUNT(sid) AS '中等率',
sum(CASE WHEN score>=80 AND score<90 THEN 1 ELSE 0 END)/COUNT(sid)AS '优良率',
sum(CASE WHEN score>=90 AND score<=100 THEN 1 ELSE 0 END)/COUNT(sid) AS '优秀率'
FROM sc a 
INNER JOIN course b
ON a.cid=b.cid
GROUP BY a.cid
ORDER BY '选课人数' DESC,a.cid ASC
--(中)17.统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[60-0] 及所占百分比
SELECT a.cid,b.cname,
concat(SUM(CASE WHEN score>=85 and score<=100 THEN 1 ELSE 0 END )/ count(sid)*100,'%')AS '100-85',
concat(SUM(CASE WHEN score>=70 and score<85 THEN 1 ELSE 0 END)/ count(sid)*100,'%')AS '70-85',
concat(SUM(CASE WHEN score>=60 and score<70 THEN 1 ELSE 0 END)/ count(sid)*100,'%')AS '70-60',
concat(SUM(CASE WHEN score>=0 and score<70 THEN 1 ELSE 0 END)/ count(sid)*100,'%')AS '60-0'
FROM sc a INNER JOIN course b
ON a.cid=b.cid
GROUP BY cid

开窗函数

-- (中)13.按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
SELECT c.sid,c.cid,e.cname,c.score,d.avg_sco FROM
(SELECT a.sid,a.cid,a.score FROM sc a INNER JOIN student b on a.sid=b.sid) c
LEFT JOIN 
(SELECT a.sid,AVG(score) as avg_sco FROM sc a  GROUP BY a.sid) d
on c.sid=d.sid
LEFT JOIN course e on c.cid=e.cid
ORDER BY avg_sco DESC
  
-- 开窗函数解法
SELECT a.sid,b.cid,b.score,avg(b.score) over ( PARTITION BY b.sid ) AS avg_sco 
FROM student a INNER JOIN sc b
ON a.sid = b.sid ORDER BY avg_sco DESC
-- (难)15.按各科成绩进行排序,并显示排名, Score 重复时保留名次空缺 
SELECT sid,cid,score,@rank:=@rank+1 FROM sc ,(select @rank:=0) r
ORDER BY score DESC
-- 开窗函数解法
select a.*, 
rank() over(partition by a.cid order by a.score desc) as rn
from sc a;


-- 15.1 按各科成绩进行排序,并显示排名, Score 重复时合并名次
SELECT sid,cid,score,CASE WHEN score=@sco THEN @rank
WHEN @sco:=score THEN @rank:=@rank+1 end as rn
FROM sc,(SELECT @rank:=0,@sco:=null)as r
ORDER BY score DESC
-- 开窗函数解法
select cid,score,dense_rank() over (partition by cid order by score desc)  as "rank" 
from sc;
-- (难)16.查询学生的总成绩,并进行排名,总分重复时保留名次空缺 
SELECT s.*,@rank:=IF(@sum_sco=sum_sco,'',@rank+1) as r,@sum_sco:=sum_sco FROM 
(SELECT sid,sum(score) AS sum_sco FROM sc 
GROUP BY sid
ORDER BY sum_sco DESC) as s,(SELECT @rank:=0,@sum_sco:=null ) as t
--窗口函数解法
select *, dense_rank() over (order by sum_score desc) as rank1
from (select sc.sid, sum(sc.score) as sum_score from sc group by sc.sid) a;

-- 16.1 查询学生的总成绩,并进行排名,总分重复时不保留名次空缺
SELECT s.*,@rank:=IF(@sum_sco=sum_sco,@rank,@rank+1) as r,@sum_sco:=sum_sco FROM 
(SELECT sid,sum(score) AS sum_sco FROM sc 
GROUP BY sid
ORDER BY sum_sco DESC) as s,(SELECT @rank:=0,@sum_sco:=null ) as t
--窗口函数解法
select *, rank() over (order by sum_score desc) as rank1 from 
(select sc.sid, sum(sc.score) as sum_score from sc group by sc.sid)a;
-- (中)18.查询各科成绩前三名的记录
     # 前三名转化为大于此成绩的数量少于3,构造笛卡尔积
SELECT a.* FROM sc a 
WHERE(select count(1) FROM sc b WHERE b.cid=a.cid and b.score>a.score)<3
ORDER BY cid asc,score desc
--窗口函数解法
select * from 
(select*,dense_rank()over(partition by cid order by score desc) as r from sc) a
where r<=3
-- (中)36.查询每门功成绩最好的前两名
SELECT a.*FROM sc a where 
(select count(sid) FROM sc b where a.cid=b.cid and b.score>a.score)<2
ORDER BY cid asc,score desc
-- (难)34.假设成绩有重复的情况下,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩
SELECT * FROM (SELECT a.*,CASE WHEN @score=score THEN @rank
                WHEN @score:=score THEN @rank:=@rank+1 END as rn FROM
(SELECT a.sid,b.sname,c.cid,c.cname,d.tname,a.score 
FROM sc a,student b,course c,teacher d 
WHERE a.sid=b.sid AND a.cid=c.cid AND c.tid=d.tid AND d.tname='张三' ) a,
(SELECT @rank:=0,@score:=null)t)s
where rn=1

--开窗函数解法
select t.* from 
(select a.sid,d.sname,b.cname,c.tname,a.score,rank()over(order by a.score desc) as r 
from sc a join course b on a.cid=b.cid
join teacher c on b.tid=c.tid
join student d on a.sid=d.sid where c.tname = '张三')t
where r=1

日期函数

-- (中)42.查询本周过生日的学生
SELECT *, SUBSTR(YEARWEEK(sage),5,2), SUBSTR(YEARWEEK(CURDATE()),5,2)
FROM student 
WHERE SUBSTR(YEARWEEK(sage),5,2)=SUBSTR(YEARWEEK(CURDATE()),5,2)

-- (中)43.查询下周过生日的学生
SELECT *, SUBSTR(YEARWEEK(sage),5,2), SUBSTR(YEARWEEK(CURDATE()),5,2)
FROM student 
WHERE SUBSTR(YEARWEEK(sage),5,2)=SUBSTR(YEARWEEK(CURDATE()),5,2)+1

-- (中)44.查询本月过生日的学生
SELECT *, month(sage), month(CURDATE())
FROM student 
WHERE  month(sage)= month(CURDATE())

-- (中)45.查询下月过生日的学生
SELECT *, month(sage), month(CURDATE())
FROM student 
WHERE  month(sage)= month(CURDATE())+1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值