SQL常用场景50题

--1.学生表

Student(SID,Sname,Sage,Ssex) --SID 学生编号,Sname 学生姓名,Sage 出生年月,Ssex 学生性别

--2.课程表

Course(CID,Cname,TID) --CID --课程编号,Cname 课程名称,TID 教师编号

--3.教师表

Teacher(TID,Tname) --TID 教师编号,Tname 教师姓名

--4.成绩表

SC(SID,CID,score) --SID 学生编号,CID 课程编号,score 分数

1、查询"01"课程比"02"课程成绩高的学生的信息及课程分数

解析:多表查询,自连接

select a.*,SC.CID,score from Student a,SC b1,SC b2

where a.SID=sc.SID and a.SID=b1.SID and a.SID=b2.SID and b1.CID='01'and b2.CID='02' and b1.score > b2.score

上面可以改写为,区别在于上面为竖排CID,下面为横排:

select a.*,b1.score,b2.score from Student a,SC b1,SC b2

where a.SID=b1.SID and a.SID=b2.SID and b1.CID='01'and b2.CID='02' and b1.score > b2.score

上面可以改写为,处理不存在02课程的情况:

select a.*,b1.score,b2.score from Student a

left join SC b1 on a.SID=b1.SID and b1.CID='01'

left join SC b2 on a.SID=b1.SID and b1.CID='02'

where b1.score > isnull(b2.score,0)

2.查询"01"课程比"02"课程成绩低的学生的信息及课程分数

解析:同上,01,02 互换就行了

3.查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩

解析:多表查询,cast(avg(b.score) as decimal(18.2)) avg_score 代替 avg(b.score) 确定精度小数位数

select a.SID,a.Sname,b.avg(score) from Student a, SC b

where a.SID=b.SID

group by a.SID,a.Sname

having avg(b.score) >= 60

order by a.SID

4.查询平均成绩小于60分的同学的学生编号和学生姓名和平均成绩

解析:同上,>= 变成 <即可;另外,如果学生表有名字,但成绩表不存在成绩可以用:

having isnull(cast(avg(b.score) as decimal(18,2)),0) < 60 代替having avg(b.score)

5.查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩

解析:多表查询

①:(有成绩)

select a.SID,a.Sname,count(b.CID) C_nm,sum(b.score) C_totalscore

from Student a , SC b

where a.SID=b.SID

group by a.SID,a.Sname

order by a.SID

②:(包括有成绩和无成绩)

select a.SID,a.Sname,count(b.CID) C_nm,sum(b.score) C_totalscore

from Student a left join SC b on a.SID=b.SID

group by a.SID,a.Sname

order by a.SID

6.查询"李"姓老师的数量

解析: like

select count(TID) T_nm_Li from Teacher where Tname like '李%' --'李%'=CONCAT('李', '%')

或者:

select count(TID) T_nm_Li from Teacher where left(Tname,1)='李'

7.查询学过"张三"老师授课的同学的信息

select a.* from Student a, SC b, Course c,Teacher d

where a.SID=b.SID and b.CID=C.CID and  c.TID=d.TID and d.Tname ='张三'

8.查询没学过"张三"老师授课的同学的信息

select * from Student where SID not in

(select a.* from Student a, SC b, Course c,Teacher d

where a.SID=b.SID and b.CID=C.CID and  c.TID=d.TID and d.Tname ='张三'

)

9.查询学过编号为"01"并且也学过编号为"02"的课程的同学的信息

解析:先查询学过01的,同时加入子查询学过02的

①:--exists

select Student.* from Student , SC

where Student.SID = SC.SID and SC.CID = '01'

and exists (Select 1 from SC SC_2 where SC_2.SID = SC.SID and SC_2.CID = '02')

order by Student.SID

②:--union all

select m.* from Student m where SID in

(

  select SID from

  (

    select distinct SID from SC where CID = '01'

    union all

    select distinct SID from SC where CID = '02'

  ) t group by SID having count(1) = 2 --记录数为2

)

order by m.SID

③:简洁

SELECT

    a.* FROM

    student a,

    sc b1,

    sc b2

WHERE a.SID = b1.SID AND a.SID = b2.SID AND b1.CID = '01' AND b2.CID = '02'

④:--

select * from Student where SID  in

(select a.SID,count(b.CID) from Student a, SC b

where a.SID=b.SID and (b.CID='01' or b.CID='02')

group by a.SID

having count(b.CID)=2

)

⑤:--

select Student.* from Student , SC

where Student.SID = SC.SID and (SC.CID = '01' or SC.CID = '02')

group by Student.SID having count(1) = 2

10.查询学过编号为"01"但是没有学过编号为"02"的课程的同学的信息

解析:先查询学过01的,同时加入子查询非学过02的

select Student.* from Student , SC

where Student.SID = SC.SID and SC.CID = '01'

and not exists (Select 1 from SC SC_2 where SC_2.SID = SC.SID and SC_2.CID = '02')

order by Student.SID

11.查询没有学全所有课程的同学的信息

解析:比较一下课程表中课程数和成绩表中每个学生的课程数,返回学生表信息

select a.* from Student a,SC b where a.SID=b.SID

group by a.SID

having count(b.CID)<(select count(c.CID) form Course)

order by a.SID

或者:

select Student.*

from Student left join SC

on Student.SID = SC.SID

group by Student.SID , Student.Sname , Student.Sage , Student.Ssex

having count(CID) < (select count(CID) from Course)

12.查询至少有一门课与学号为"01"的同学所学相同的同学的信息

解析:比较其他学生和01学生课程名称、in、distinct 避免重复

select distinct a.* from Student a,SC b where a.SID<>'01'and a.SID=b.SID and b.CID in

(select CID from SC where SID='01')

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

解析:在上面的基础上,多加一个查询记录和01学生课程记录数相等即可

select distinct a.* from Student a,SC b where a.SID<>'01'and a.SID=b.SID and b.CID in

(select CID from SC where SID='01')

group by a.SID,a.Sname , a.Sage , a.Ssex

having count(b.CID)=(select count(CID) from SC where SID='01')

select Student.* from Student where SID in

(select distinct SC.SID from SC where SID <> '01'

and SC.CID in (select distinct CID from SC where SID = '01')

group by SC.SID having count(1) = (select count(1) from SC where SID='01')

)

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

解析:查询张三老师讲授过的学生名字,not in

select * from Student where SID not in

(select distinct a.SID from SC a,Course b, Teacher c

where a.CID=b.CID and b.TID=c.TID and c.Tname='张三')

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

select a.SID,a.Sname,avg(b.score) from Student a,SC b

where a.SID=b.SID and a.SID in (select SID from SC where score <60 group by SID count(1)>=2)

group by a.SID,a.Sname

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

select a.*,b.score from Student a, SC b where b.SID='01'and b.score <60 and a.SID=b.SID

order by b.score DESC

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

解析:按照文字题意,展示所有课程的成绩及平均成绩,可以有两周展示方案,

第一种列分布各科成绩及平均成绩(推荐);第二种行分布

select a.Sname,

sum(case when c.Cname='语文' then b.score else null end) Score_chinese,

sum(case when c.Cname='数学' then b.score else null end) Score_math

--(.......)

avg(score) avg_score

from Student a

left join SC b on a.SID=b.SID

left join Course c on b.CID=c.CID

group by a.Sname

order by avg(score) DESC

18.查询各科成绩最高分、最低分和平均分:以如下形式显示

课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率

--及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90

解析:这里的*100 加不加就是结果是 72.22 与结果是 0.72 的区别 最好加|| ‘%’?

select m.CID  课程编号 , m.Cname  课程名称 ,

  max(n.score)  最高分 ,

  min(n.score)  最低分 ,

  cast(avg(n.score) as decimal(18,2))  平均分 ,

  cast((select count(1) from SC where CID = m.CID and score >= 60)*100.0 / (select count(1) from SC where CID = m.CID) as decimal(18,2))  及格率 ,

  cast((select count(1) from SC where CID = m.CID and score >= 70 and score < 80 )*100.0 / (select count(1) from SC where CID = m.CID) as decimal(18,2))  中等率 ,

  cast((select count(1) from SC where CID = m.CID and score >= 80 and score < 90 )*100.0 / (select count(1) from SC where CID = m.CID) as decimal(18,2))  优良率 ,

  cast((select count(1) from SC where CID = m.CID and score >= 90)*100.0 / (select count(1) from SC where CID = m.CID) as decimal(18,2))  优秀率

from Course m , SC n

where m.CID = n.CID

group by m.CID , m.Cname

order by m.CID

和下面基本没有啥区别,上面是直接max聚合的,需要后面写好 group by ,下面是直接写好最高的select的

select m.CID  课程编号 , m.Cname  课程名称 ,

  (select max(score) from SC where CID = m.CID)  最高分 ,

  (select min(score) from SC where CID = m.CID)  最低分 ,

  (select cast(avg(score) as decimal(18,2)) from SC where CID = m.CID)  平均分 ,

  cast((select count(1) from SC where CID = m.CID and score >= 60)*100.0 / (select count(1) from SC where CID = m.CID) as decimal(18,2))  及格率,

  cast((select count(1) from SC where CID = m.CID and score >= 70 and score < 80 )*100.0 / (select count(1) from SC where CID = m.CID) as decimal(18,2))  中等率 ,

  cast((select count(1) from SC where CID = m.CID and score >= 80 and score < 90 )*100.0 / (select count(1) from SC where CID = m.CID) as decimal(18,2))  优良率 ,

  cast((select count(1) from SC where CID = m.CID and score >= 90)*100.0 / (select count(1) from SC where CID = m.CID) as decimal(18,2))  优秀率

from Course m

order by m.CID

19.按各科成绩进行排序,并显示排名

解析:rank() over ( partition by order by )  保留名次空缺和合并名次

select a.*,rank() over(partition by CID order by CID DESC ) as rank  from SC a order by a.CID, rank

20.查询学生的总成绩并进行排名

解析:查询总成绩 然后排序 根据需要可以分 rank 还是 dense rank

select b.*,rank() over (order by score_total desc) rank from

(select a.SID,a.Sname,isnull(sum(b.score),0)score_total from Student a

left join SC b on a.SID=b.SID

group by a.SID,a.Sname

) b

order by rank

21.查询不同老师所教不同课程平均分从高到低显示

select a.Tname,b.CID,avg(c.score) avg_score from Teacher a

left join Course b on a.TID=b.TID

left join SC c on b.CID=c.ICD

group by a.Tname,b.CID

order by avg_score desc

22.查询所有课程的成绩第2名到第3名的学生信息及该课程成绩

解析:partition by CID, having rank between 2 to 3

select a.*,b.score,rank() over (partition by CID order by score) rank from

Student a,SC b where a.SID=b.SID and (rank between 2 to 3 )

select * from 

(select t.* , px = rank() over(partition by cid order by score desc) from sc t) m

where px between 2 and 3 

order by m.CID , m.px

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

解析: two question 分数段人数和占比 count(1) case when then else end 

排列:分数段作为c列字段值,人数和占比作为d、f列字段名;或者分数段及占比作为c、d、e、f、g、h、i、j列字段名,即分为纵向和横向显示两种结果。

select a.CID,b.Cname,

    case when score>=85 then '100-85'

      when score>=70 and score<85 then '85-70'

      when score>=60 and score<70 then '70-60'

      when score<60 then '0-60' End

as flag,

count(1) as S_nm

count(1)/(select count(1) from a where a.CID=b.CID) as S_nm%

from SC a, Course b

where a.CID=b.CID

group by a.CID,b.Cname,

case when score>=85 then '100-85'

      when score>=70 and score<85 then '85-70'

      when score>=60 and score<70 then '70-60'

      when score<60 then '0-60' End

order by a.CID,b.Cname,flag

不存在的分数段显示0:

select m.CID  课程编号  , m.Cname  课程名称  , 分数段 = (

  case when n.score >= 85 then '85-100'

       when n.score >= 70 and n.score < 85 then '70-85'

       when n.score >= 60 and n.score < 70 then '60-70'

       else '0-60'

  end) ,

  count(1) 数量 ,  

  cast(count(1) * 100.0 / (select count(1) from sc where CID = m.CID) as decimal(18,2))  百分比

from Course m , sc n

where m.CID = n.CID

group by all m.CID , m.Cname , (

  case when n.score >= 85 then '85-100'

       when n.score >= 70 and n.score < 85 then '70-85'

       when n.score >= 60 and n.score < 70 then '60-70'

       else '0-60'

  end)

order by m.CID , m.Cname , 分数段

横向显示:

select m.CID 课程编号, m.Cname 课程名称,

  (select count(1) from SC where CID = m.CID and score < 60)  0-60 ,

  cast((select count(1) from SC where CID = m.CID and score < 60)*100.0 / (select count(1) from SC where CID = m.CID) as decimal(18,2))  百分比 ,

  (select count(1) from SC where CID = m.CID and score >= 60 and score < 70)  60-70 ,

  cast((select count(1) from SC where CID = m.CID and score >= 60 and score < 70)*100.0 / (select count(1) from SC where CID = m.CID) as decimal(18,2))  百分比 ,

  (select count(1) from SC where CID = m.CID and score >= 70 and score < 85)  70-85 ,

  cast((select count(1) from SC where CID = m.CID and score >= 70 and score < 85)*100.0 / (select count(1) from SC where CID = m.CID) as decimal(18,2))  百分比 ,

  (select count(1) from SC where CID = m.CID and score >= 85)  85-100 ,

  cast((select count(1) from SC where CID = m.CID and score >= 85)*100.0 / (select count(1) from SC where CID = m.CID) as decimal(18,2))  百分比

from Course m

order by m.CID

24.查询学生平均成绩及其名次

解析:类似第20题

select b.*,rank() over (order by avg_total desc) rank from

(select a.SID,a.Sname,isnull(avg(b.score),0)avg_total from Student a

left join SC b on a.SID=b.SID

group by a.SID,a.Sname

) b

order by rank

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

解析:先排序,然后取前三

select * from

(

select a.*,rank()over (partition by b.CID order by b.score DESC ) rank from Student a,SC b where a.SID=b.SID

)

where rank between 1 to 3

26.查询每门课程被选修的学生数

select a.CID,a.Cname ,count(b.SID) from Course a,SC b where a.CID=b.CID group by a.CID,a.Cname

27.查询出只有两门课程的全部学生的学号和姓名

select a.SID,a.Sname from Student a,SC b where a.SID=b.SID

group by a.SID,a.Snmae

having count(b.CID)=2

28.查询男生、女生人数

select case when Ssex='男' then 'male' when Ssex='女' then 'famale' END as gander ,count(1) as nm from Student

group by case when Ssex='男' then 'male' when Ssex='女' then 'famale' end

select Ssex as '性别',COUNT(1) as '人数' from Student group by Ssex

29.查询名字中含有"风"字的学生信息

select * from Student where Sname like '%风%'

30.查询同名同性学生名单,并统计同名人数

解析:查询出来,记录数大于等于2即可

select Sname,Ssex, count(1) from Student

group by Sname,Ssex

having count(1)>1

31.查询1990年出生的学生名单

解析:限定年份即可 substr(Sage,1,4)='1990'

select * from Student where year(sage) = 1990

select * from Student where datediff(yy,sage,'1990-01-01') = 0

select * from Student where datepart(yy,sage) = 1990

select * from Student where convert(varchar(4),sage,120) = '1990'

32.查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列

解析:排序

select m.CID , m.Cname , cast(avg(n.score) as decimal(18,2)) avg_score

from Course m, SC n

where m.CID = n.CID   

group by m.CID , m.Cname

order by avg_score desc, m.CID asc

33.查询平均成绩大于等于85的所有学生的学号、姓名和平均成绩

解析:having

select a.SID , a.Sname , cast(avg(b.score) as decimal(18,2)) avg_score

from Student a , sc b

where a.SID = b.SID

group by a.SID , a.Sname

having cast(avg(b.score) as decimal(18,2)) >= 85

order by a.SID

34.查询课程名称为"数学",且分数低于60的学生姓名和分数

select sname , score

from Student , SC , Course

where SC.SID = Student.SID and SC.CID = Course.CID and Course.Cname ='数学' and score < 60

35.查询所有学生的课程及分数情况

解析:用left join比较好

select Student.Sname , Course.Cname , SC.score 

from Student, SC , Course

where Student.SID = SC.SID and SC.CID = Course.CID

order by Student.SID, SC.CID

select a.Sname,c.Cname,b.score from Student a

left join SC b on a.SID=b.SID

left join Course on b.CID=c.ICD

order by a.Sname,c.Cname

36.查询任何一门课程成绩在70分以上的姓名、课程名称和分数

select Student.Sname , Course.Cname , SC.score 

from Student, SC , Course

where Student.SID = SC.SID and SC.CID = Course.CID and score>70

order by Student.SID, SC.CID

37.查询不及格的课程

select Student.Sname , Course.Cname , SC.score 

from Student, SC , Course

where Student.SID = SC.SID and SC.CID = Course.CID and score<60

order by Student.SID, SC.CID

38.查询课程编号为01且课程成绩在80分以上的学生的学号和姓名

select Student.SID, Student.CID  

from Student, SC

where Student.SID = SC.SID and SC.CID = '01' and SC.score >= 80

order by Student.SID , Student.CID

39.求每门课程的学生人数

select Course.Cname , count(1)  学生人数 

from Course , SC

where Course.CID = SC.CID

group by Course.Cname

order by Course.Cname

40.查询选修"张三"老师所授课程的学生中,成绩最高的学生信息及其成绩

解析:子查询为张三老师授课学生SID

select Student.* , Course.Cname ,SC.score 

from Student, SC , Course , Teacher

where Student.SID = SC.SID and SC.CID = Course.CID and Course.TID = Teacher.TID and Teacher.Tname = '张三' and

SC.score = (select max(SC.score) from SC , Course , Teacher where SC.CID = Course.CID and Course.TID = Teacher.TID and Teacher.Tname = '张三')

当前考虑张三老师教了多门课,取总成绩最高

select Student.* , Course.Cname ,SC.score 

from Student, SC , Course , Teacher

where Student.SID = SC.SID and SC.CID = Course.CID and Course.TID = Teacher.TID and Teacher.Tname = '张三' and

Student.SID in

(select SID from

(select a.SID,sum(SC.score),rank() over(partition by SID order by sum(SC.score) desc) as rank from SC a, Course b , Teacher c

where a.CID = b.CID and b.TID =c.TID and c.Tname = '张三' and rank=1

group by a.SID)

)

41.查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩

select a.* from SC a ,

(select CID , score from SC group by CID , score having count(1) > 1) b

where a.CID= b.CID and a.score = b.score

order by a.CID , a.score , a.SID

select m.* from SC m

where

exists

      (select 1 from

      (select CID , score from SC group by CID , score having count(1) > 1) n

      where m.CID= n.CID and m.score = n.score

  )

order by m.CID , m.score , m.SID

42.查询每门功成绩最好的前两名

select a.* from sc a where score in

(select top 2 score from sc where CID = T.CID order by score desc)

order by a.CID , a.score desc

select a.* from SC a where a.SID in

(select SID from

        (select SID,rank() over(partition by CID order by score desc) as rank where rank=2)

)

order by a.CID , a.score desc

43.统计每门课程的学生选修人数(超过5人的课程才统计)。要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列

select Course.CID , Course.Cname , count(*)  学生人数 

from Course , SC

where Course.CID = SC.CID

group by  Course.CID , Course.Cname

having count(*) >= 5

order by  学生人数  desc , Course.CID

44.检索至少选修两门课程的学生学号

select SID from SC group by SID

having count(1) >= 2

order by SID

45.查询选修了全部课程的学生信息

解析:课程表数量和成绩表中数量即可

select student.* from student where SID in

(select SID from sc group by SID having count(1) = (select count(1) from course))

46.查询各学生的年龄

select * , datediff(yy , sage , getdate())  年龄  from student

select * ,

case when right(convert(varchar(10),getdate(),120),5) < right(convert(varchar(10),sage,120),5) then datediff(yy , sage , getdate()) - 1

else datediff(yy , sage , getdate()) end   --为什么不是102而是120 ,也可以用substr

年龄  from student

47.查询本周过生日的学生

select * from student where datediff(week,datename(yy,getdate()) - right(convert(varchar(10),sage,120),6),getdate()) = 0

select * from student where ((select WEEKOFYEAR(now()))- (select WEEKOFYEAR(sage))) =0

48.查询下周过生日的学生

select * from student where datediff(week,datename(yy,getdate()) - right(convert(varchar(10),sage,120),6),getdate()) = -1

select * from student where ((select WEEKOFYEAR(now()))- (select WEEKOFYEAR(sage))) = -1

49.查询本月过生日的学生

select * from student where datediff(mm,datename(yy,getdate()) - right(convert(varchar(10),sage,120),6),getdate()) = 0

select * from student where ((select month(now()))- (select month(sage))) = 0

50.查询下月过生日的学生

select * from student where datediff(mm,datename(yy,getdate()) - right(convert(varchar(10),sage,120),6),getdate()) = -1

select * from student where ((select month(now()))- (select month(sage))) = -1

你可能感兴趣的:(SQL常用场景50题)