SQL经典50题

时间:2021-10-17 16:44:20

用到的表的介绍

student: sid(学生ID),sname(学生姓名),sage,ssex
course: cid(课程ID),cname,tid(教师ID)
teacher: tid,tname
sc:sid,cid,score

 

只是附上题目和代码,没有运行结果

1.查询"01"课程比"02"课程成绩高的学生的信息及课程分数
select *
from 
    (select t1.sid,class1,class2
    from
        (select sid,score as class1 from sc where cid=01 )as t1
    join
        (select sid,score as class2 from sc where cid=02) as t2
    on t1.sid=t2.sid and t1.class1>t2.class2
    )r
left join student
on r.sid=student.sid 
;

1.1 查询存在" 01 "课程但可能不存在" 02 "课程的情况(不存在时显示为 null )
select *
from
    (select * from sc where cid=01)t1
left join
    (select * from sc where cid=02)t2
on t1.sid=t2.sid
;

1.2 查询同时存在01和02课程的情况
select *
from
    (select * from sc where cid=01
    )t1
join (select * from sc where cid=02
    )t2
on t1.sid =t2.sid
;

1.3 查询选择了02课程但没有01课程的情况
select * from sc where cid=02 and sid not in (
            select sid from sc where cid=01)
;

2.查询平均成绩大于等于 60 分的同学的学生编号和学生姓名和平均成绩
select t1.sid,t1.meanscore,student.sname
from 
    (select sid,avg(score)as meanscore
     from sc 
     group by sid
     having avg(score)>=60
    )t1
left join student
on t1.sid=student.sid
;

3.查询在 SC 表存在成绩的学生信息
select distinct student.*
from sc 
join student
on sc.sid=student.sid
;

4.查询所有同学的学生编号、学生姓名、选课总数、所有课程的成绩总和
select r.*,student.sname
from 
    (select sid, count(distinct cid) as qcourse,sum(score)as sumscore
     from sc 
     group by sid 
    )r
left join student
on r.sid=student.sid
;


5.查询「李」姓老师的数量
select count(*) from teacher where tname like (李%)
;

6.查询学过「张三」老师授课的同学的信息
select student.*
from 
    (select * from teacher where tname= 张三
    )t1
left join course 
on t1.tid=course.tid
left join sc 
on course.cid=sc.cid
left join student
on sc.sid=student.sid
;

@7.查询没有学全所有课程的同学的信息
select student.*,qcourse
from 
    (select sid,count(distinct cid) as qcourse
    from sc 
    group by sid
    having count(distinct cid)<(select count(distinct cid) from course)
    )
left join student
on sc.sid=student.sid
;

@8.查询至少有一门课与学号为" 01 "的同学所学相同的同学的信息
select student.*
from sc
join student
on sc.sid=student.sid
where sc.cid in (select cid from sc where sid =01
                    )
    and sc.sid !=01
group by sc.sid
;

@9.查询和" 01 "号的同学学习的课程完全相同的其他同学的信息

10.查询没学过"张三"老师讲授的任一门课程的学生姓名
select sname
from student
where sid not in(select sid from sc 
                 left join course 
                 on sc.cid=course.cid
                 left join teacher
                 on course.tid=teacher.tid
                 where teacher.tname !=张三)
;

11.查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
select t1.*,student.sname
from
    (select sid,avg(score)as meanscore
    from sc
    where sid in (select sid,count(distinct cid)
              from sc
              where score<60
              group by sid
              having count(distinct cid)>=2)
    )t1
left join student
on t1.sid=student.sid
;

12.检索" 01 "课程分数小于 60,按分数降序排列的学生信息
select student.*,t1.score
from 
    (select *
    from sc
    where cid=01
        and score<60
    )t1
left join student
on t1.sid=student.sid
order by t1.score desc
;

13.按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
select sc.*,t1.meanscore
from sc
left join
    (select sid,avg(score) as meanscore
    from sc 
    group by cid
    )t1
on sc.sid=t1.sid
order by t1.meanscore
;

14.查询各科成绩最高分、最低分和平均分,以如下形式显示:
课程 ID,课程 name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率
及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90
要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序
排列
select cid as 课程 ID,
        count(sid) as 课程人数,
        max(score) as 最高分,
        min(score) as 最低分,
        avg(score) as 平均分,
        cast(cast sum(及格) as double)/(cast count(sid) as double) as 及格率,
        SUM(中等) / COUNT(sid) AS 中等率,
        SUM(优良) / COUNT(sid) AS 优良率,
        SUM(优秀) / COUNT(sid) AS 优秀率
from 
    (select *,
            case when score >=60 then 1 else 0 end as 及格,
            case when score>=70 and score<80 then 1 else 0 end as 中等 ,
            case when score >=80 and score<90 then 1 else 0 end as 优良,
            case when score >=90 then 1 else 0 end as 优秀
    from sc
    )a 
group by cid
order by count(sid)desc,cid
;

@15.按各科成绩进行排序,并显示排名, Score 重复时保留名次空缺
select a.*,count(a.score) as 排名
from sc a
left join sc b
on a.sid=b.sid
    and a.score < b.score
group by a.cid,a.sid,a.score
order by a.cid
;
--用sc中的score和自己进行对比,来计算“比当前分数高的分数有几个”。

@15.1 按各科成绩进行行排序,并显示排名, Score 重复时合并名次
select a.*,count(b.score) 1 as 排名
from sc a
left join sc b
on a.sid=b.sid
    and a.score < b.score
group by a.cid,a.sid,a.score
order by a.cid
;

@16.查询学生的总成绩,并进行排名,总分重复时保留名次空缺
select a.*,@rank:=@rank 1 as rank 
from 
    (select sid,
            sum(score)
    from sc
    group by sid
    order by sum(score)desc
    )a,
    (select @rank:=0
    )b 
;

17. 统计各科成绩各分数段人数:课程编号,课程名称,[100-85][85-70][70-60][60-0] 及所占百分比
select a.*,course.cname
from
    (select cid,
            sum(case when score>=85 and score <=100 then 1 else 0 end )/count(distinct sid) as [100-85],
            sum(case when score>=70 and score <85 then 1 else 0 end )/count(distinct sid) as [85-75],
            sum(case when score>=60 and score <70 then 1 else 0 end )/count(distinct sid) as [70-60],
            sum(case when score <60 then 1 else 0 end )/count(distinct sid) as [60-0]
    from sc 
    group by cid
    )a
left join course
on a.cid =course.cid
;

18.查询各科成绩前三名的记录
select a.*,count(b.score) 1 as ranking
from sc as a
left join sc as b
on a.cid=b.cid and a.score<b.score
group by a.cid,a.sid 
having ranking <=3
order by a.cid,ranking
--having where不能使用别名,group by order by中可以使用别名
--
select *
from
    (select *,row_number()over(partition by cid order by score desc)as ranking 
    from sc)
where ranking>=3
;

19.查询每门课程被选修的学生数
select cid,count(distinct sid) as num
from sc 
group by cid 
;

20.查询出只选修两门课程的学生学号和姓名
select sc.sid,student.sname
from sc
left join student
on sc.sid=student.sid
group by sc.cid
having count(cid)=2
;

21. 查询男生、女生人数
select count(case when ssex= then sid else null end)as 男生人数,
        count(case when ssex= then sid else null end)as 女生人数
from student
;

22. 查询名字中含有「风」字的学生信息
select *
from student
where sname like %风%
;

23查询同名同性学生名单,并统计同名人数
select sname,count(ssex)
from student
group by sname
having count(ssex)>1
;

24.查询 1990 年出生的学生名单
select *
from student
where year(sage) like1990%
;

25.查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
select cid,avg(score)as meanscore
from sc 
group by cid
order by meanscore desc,cid
;

26.查询平均成绩大于等于 85 的所有学生的学号、姓名和平均成绩
select a.sid,student.sname,a.meanscore
from 
    (select sid,avg(score) as meanscore
    from sc 
    group by sid
    having avg(score)>=85
    )a
left join student
on a.sid=student.sid
;

27.查询课程名称为「数学」,且分数低于 60 的学生姓名和分数
select student.sname,b.socre
from
    (select cid
    from course
    where cname =数学
    )a
left join 
    (select *
    from sc
    where score<60
    )b
on a.cid=b.cid
left join student
on b.sid=student.sid
;

28. 查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)
select sname,sc.cid,sc.score
from sc
join student
on sc.sid=student.sid
;

29.查询任何一门课程成绩在 70 分以上的姓名、课程名称和分数
select sname,sc.cid,sc.score
from sc
join student
on sc.sid=student.sid
where sc.score >70
;

30.查询不及格的课程
select distinct cid
from sc 
where score<60
;

31.查询课程编号为 01 且课程成绩在 80 分以上的学生的学号和姓名
select sc.sid,sname
from
    (select *
    from sc 
    where cid=01and score>80
    )a 
left join student
on a.sid=student.sid
;

32.求每门课程的学生人数
select cid, count(sid)as cnt
from sc
group by cid
;

33.成绩不重复,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩
select student.*,sc.score
from
    (select tid
    from teacher
    where tname=张三
    )a
left join course
on a.tid=course.tid
left join sc
on course.cid=sc.cid
left join student
on sc.sid=student.sid
order by sc.score desc
limit 1
;

34.成绩有重复的情况下,查询选修「张三」老师所授课程的学生中,成绩最高的学生

35.查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩
select distinct a.*
from sc as a
join sc as b
on a.score=b.score 
    and a.cid!=b.cid
;


36. 查询每门成绩最好的前两名
select *
from 
    (select *,
        row_number()over(partition by cid order by score desc)as ranking
    )
where ranking <=2
;
--方法2自交
select *
from sc
where (select count(*)
        from sc as a 
        where sc.cid=a.cid
            and sc.score<a.score
        )<2
order by cid ,sc.score desc
;

37. 统计每门课程的学生选修人数(超过 5 人的课程才统计)
select cid,count(sid)
from sc
group by sc
having count(sid)>5
;

38.检索至少选修两门课程的学生学号
select cid,count(sid)
from sc
group by sc
having count(sid)>2
;

39.查询选修了全部课程的学生信息
select student.*
from
    (select sid
    from sc 
    where cid =(select count(distinct cid) from course 
                )
    )a 
left join student
on a.sid=student.sid
;

40.查询各学生的年龄,只按年份来算
select sname,year(now())-year(age) as 年级
from student
;

41. 按照出生日期来算,当前月日 < 出生年月的月日则,年龄减一
select sname,    
        case when (date_format(now(),%m-%d)-date_format(sage,%m-%d)<0 
        then year(now())-year(sage) 1
        else year(now())-year(sage)
        end as 年龄
from student
;
--date_format转化为时间戳,利用时间戳求差值

42.查询本周过生日的学生
select * 
from student
where weekofyear(date_format(now(),%y%m%d))
        =
      weekofyear(date_format(sage,%y%m%d)-date_format(sage,%y)*10000 date_format(now(),%y)*10000)
;
--出生日期的年份去掉,得到月份和日期,再拼接上当前的年份
--weekofyear函数是计算出当前日期所在周数


43. 查询下周过生日的学生
select * 
from student
where weekofyear(date_format(now(),%y%m%d)) 1
        =
      weekofyear(date_format(sage,%y%m%d)-date_format(sage,%y)*10000 date_format(now(),%y)*10000)
;

44.查询本月过生日的学生
select sname
from student
where month(sage)=month(now())
;

45.查询下月过生日的学生
select sname
from student
where month(sage)=month(now()) 1
;