sql经典50题(附自己测试成功的详细具体答案)

文章目录

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

# 方法1思路 在课程和学生中间表中,按照学生分组,得到每个学生的全部课程,然后挑选查询出01课程的和02课程的,
# 然后对分组后的结果过滤出"01"课程比 "02" 课程成绩高的学生,然后与学生表连接得到学生信息以及分数
# 查询"01"课程比 "02" 课程成绩高的学生
select s_id, max(case when  c_id ='01' then score else 0 end)score01,max(case when  c_id ='02' then score else 0 end) score02
from sc
group by s_id
having score01 >score02;

# 查询"01"课程比 "02" 课程成绩高的学生的信息及课程分数
select s.*,temp.score01,temp.score02
from student  as s
inner join (
select s_id, max(case when  c_id ='01' then score else 0 end)score01,max(case when  c_id ='02' then score else 0 end) score02
from sc
group by s_id
having score01 >score02) as temp
on s.s_id =temp.s_id;

#方法2思路:分两种情况:  (1)"01"课程、 "02" 课程成绩都存在。(2) "01"课程存在,但“02”课程成绩不存在(3)合并,然后与学生表连接得到学分数

select  sc01.s_id, sc02.s_id ,sc01.c_id,sc02.c_id,  sc01.score,sc02.score
from sc as sc01
inner join  sc as sc02
on sc01.c_id='01'  and  sc02.c_id='02'
where  (sc01.s_id=sc02.s_id and sc01.score>sc02.score)
union all
select  sc01.s_id, sc02.s_id ,sc01.c_id,sc02.c_id,  sc01.score,sc02.score
from sc as sc01
         left join  sc as sc02
                     on  sc01.s_id=sc02.s_id and  sc02.c_id='02'
where   sc01.c_id='01'  and  sc01.score is not  null and  sc02.score is null;

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

# 方法一
select s.s_id,s.s_name,temp.average
from  student  as s
          inner join
      (select s_id, round( avg(score),1)  average
       from sc
       group by  s_id
       having  avg(score)>=60 ) as temp
      on s.s_id =temp.s_id;
# 方法2
select s.s_id,s.s_name, round( avg(sc.score),1)  average
from sc
         inner join student as s
                    on s.s_id =sc.s_id
group by  sc.s_id,s.s_name
having  avg(sc.score)>=60;

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

select s.s_id,s.s_name,temp.count,temp.sum
from student as s
         left join
     (select s_id, count(c_id) as count,sum(score)  as sum from sc
      group by s_id) as temp
     on s.s_id =temp.s_id;

4.查询姓“张”的老师个数

select count(*) as count
from teacher
where t_name like '张%';

5.查询没学过张三老师课的学生的学号和姓名

# 方法1
select  s.s_id,s_name from student as s where  s_id  in(select s_id from sc where  c_id in(
    select c_id from course as c
    where t_id   not in
          (select t_id
           from teacher
           where t_name ='张三')));
# 方法2
select   distinct (s.s_id),s_name from student as s
                                           left join sc
                                                     on s.s_id =sc.s_id
                                           left join course as c
                                                     on sc.c_id = c.c_id
                                           left  join  teacher as t
                                                       on c.t_id = t.t_id
where  t.t_name <>'张三' ; 

6.查询学过张三老师所教的所有课程的同学的学号和姓名

select   distinct (s.s_id),s_name from student as s
                                           inner join sc
                                                      on s.s_id =sc.s_id
                                           inner join course as c
                                                      on sc.c_id = c.c_id
                                           inner  join  teacher as t
                                                        on c.t_id = t.t_id
where  t.t_name  = '张三';

7.查询学过01课程并且学过02课程的学生

select s.* from sc as sc1
                    inner join sc as sc2
                               on sc1.s_id =sc2.s_id
                    inner  join student as s
                                on s.s_id=sc1.s_id
where sc1.c_id='01' and  sc2.c_id='02'; 

8.查询学过02课程的总成绩

select sum(score)  as sum
from sc
where c_id ='02';

9.查询所有课程成绩小于60的学生

select s.s_id from course as c
                       left join  sc
                                  on c.c_id =sc.c_id
                       left join student as s
                                 on sc.s_id =s.s_id
group by  s.s_id
having max(sc.score)<60;

10.查询没有学全所有课的学生学号、姓名

select s.s_id ,s_name from
    student as s
        inner join  sc
                    on sc.s_id =s.s_id
        inner  join  course  as c
                     on sc.c_id =c.c_id
group by s.s_id ,s_name
having count(distinct c.c_id) <>(select  count(*) from course);

11.查询至少有一门课与学号为“01”的学生所学课程相同的学生学号、姓名

# (1)查询学号为“01”的学生所学课程
select  c_id  from sc  where s_id ='01';
#   (2)查询课程号在 (1)里的学生号,不包括自己
select  distinct s_id
         from  sc
         where c_id in
        (select  c_id  from sc  where s_id ='01') and s_id<>'01';
#   (3)根据学号查询对应信息
select s_id,s_name
from student
where s_id in
      (select  distinct s_id
       from  sc
       where c_id in
             (select  c_id  from sc  where s_id ='01') and s_id<>'01');

12.查询和“01”学号学生所学课程完全相同的学生学号

#(1)查询学号为“01”的学生所学课程
select group_concat(c_id) as c_id_001
from  sc group by s_id
having s_id='01';
# (2)查询课程号和(1)完全相同学生号,不包括自己
select  s_id
from  sc
where s_id <>'01'
group by s_id
having group_concat(c_id)=(select group_concat(c_id) as c_id_001
                           from  sc group by s_id
                           having s_id='01');

# (3)根据学号查询对应信息
select s_id,s_name
from student
where s_id in (select  s_id
               from  sc
               where s_id <>'01'
               group by s_id
               having group_concat(c_id)=(select group_concat(c_id) as c_id_001
                                          from  sc group by s_id
                                          having s_id='01'));

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

select  s.s_name
from teacher as t
         left join course as c
                   on c.t_id=t.t_id
         left join  sc
                    on sc.c_id=c.c_id
         left join student as s
                   on sc.s_id =s.s_id
where t_name is null or    t_name <> '张三'

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

select s.s_id,s.s_name, round( avg(sc.score),1)  average
from sc
         inner join student as s
                    on s.s_id =sc.s_id
group by  sc.s_id,s.s_name
having  avg(sc.score)<60;

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

# (1)查询两门及其以上不及格的学生
select s_id
from sc  where score<60
group by  s_id
having  count(score) >=2;
# (2)连接学生表和学生课程中间表 根据(1)的学生条件过滤
select s.s_id,s_name,round( avg(sc.score),1) as average_score  from student as s
                                                               inner join sc
                                                                          on s.s_id =sc.s_id
where  s.s_id in (select s_id
                  from sc  where score<60
                  group by  s_id
                  having  count(score) >=2)
group by s.s_id,s_name;

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

select s.* ,sc.score from student as s
                              inner join sc
                                         on s.s_id =sc.s_id
where sc.c_id='01' and sc.score<60
order by  sc.score desc;   

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

# (1)所有学生的所有课程的平均成绩
select s.s_id, round(avg(sc.score)) as average
from student as s
         left join sc
                   on sc.s_id =s.s_id
group by s.s_id;
# (2)连接(1)和学生课程中间表,然后得到成绩,并按平均成绩从高到低显示
select temp.s_id,sc.score, temp.average_score
from sc
         right join (select s.s_id, round(avg(sc.score)) as average_score
                     from student as s
                              left join sc
                                        on sc.s_id =s.s_id
                     group by s.s_id) as temp
                    on sc.s_id =temp.s_id
order by temp.average_score desc;

18.查询各科成绩最高分、最低分、平均分、及格率、中等率、优良率、优秀率

#及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90
#方法1:
select max(score) 最高分,min(score)最低分,round(avg(score),1)平均分 ,
       concat( round(count(case when score>=60 then score  end)/count(score)*100,1),'%') 及格率,
       concat( round(count(case when score>=70 and score<80 then score  end)/count(score)*100,1),'%') 中等率,
       concat( round(count(case when score>=80 and score<90 then score  end)/count(score)*100,1),'%') 优良率,
       concat( round(count(case when score>=90 then score  end)/count(score)*100,1),'%') 优秀率
from sc
group by c_id;
#方法2改进:
select max(score) 最高分,min(score)最低分,round(avg(score),1)平均分 ,
       format(sum(case when score>=60 then 1 else 0  end)*100/nullif(count(score),0) ,1)  as 及格率,
       format(sum(case when score>=70 and score<80 then 1 else 0  end)*100/nullif(count(score),0) ,1)  as 中等率,
       format(sum(case when score>=80 and score<90 then 1 else 0  end)*100/nullif(count(score),0) ,1)  as 优良率,
       format(sum(case when score>=90 then 1 else 0  end)*100/nullif(count(score),0) ,1)  as 优秀率
from sc
group by c_id;

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

select row_number() over (order by sum(sc.score) desc) as 排名  ,coalesce( c.c_name,'无') as 科目, sum(sc.score)as 各科总分
from sc
left join course as c
on sc.c_id =c.c_id
group by sc.c_id, coalesce( c.c_name,'无')

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

select s_id,sum(score) as 总成绩,row_number() over (order by  sum(score) desc)  as 排名
from sc  group by s_id;

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

select  t.t_id, c.c_id  ,round(avg(sc.score),1)  as average_score from  teacher as t
inner  join  course as c
on t.t_id = c.t_id
inner join sc
on sc.c_id=c.c_id
group by   t.t_id, c.c_id
order by average_score desc

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

# (1)查询所有课程的全部成绩排名的学生信息及该课程成绩
select c.c_id, s.*,sc.score,dense_rank() over (partition by sc.c_id order by sc.score) as _rank
    from course as c
    inner join sc on sc.c_id =c.c_id
    inner join student as s  on sc.s_id =s.s_id
# (2)过滤中成绩第二名和第三名的
 select * from (select c.c_id, s.*,sc.score,dense_rank() over (partition by sc.c_id order by sc.score) as _rank
                from course as c
                         inner join sc on sc.c_id =c.c_id
                         inner join student as s  on sc.s_id =s.s_id)  as rn
         where rn._rank in (2,3);

23.使用分段来统计各科成绩,分别统计各分数段人数:课程ID和课程名称

# 及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90
#    (1).为分数分配等级
select s_id,c_id, (case when score <60 then  '不及格'
             when score <70 then  '及格'
             when score <80 then  '中等'
             when score <90 then  '优良'
             else  '优秀'   end) as score_grade
from sc;
# (2)把(1)表和学生表连接并分区
select c.c_id,c.c_name, sg.score_grade,count(*) as num
from course as c
inner join (select s_id,c_id, (case when score <60 then  '不及格'
                                   when score <70 then  '及格'
                                   when score <80 then  '中等'
                                   when score <90 then  '优良'
                                   else  '优秀'   end) as score_grade
           from sc) as sg  on c.c_id  =sg.c_id
group by c.c_id,c.c_name,sg.score_grade
order by  c.c_id;

24.查询学生平均成绩以及排名

select  s.s_id,round( avg(sc.score),1) as average_score,dense_rank() over (order by avg(sc.score) desc)  as ranking from student as s
left join  sc
on sc.s_id = s.s_id
group by s.s_id;

25.查询各科成绩前三名的记录(不考虑成绩并列情况)


select * from (select  sc.c_id,sc.score,s.*,dense_rank()  over (partition by sc.c_id order by sc.score desc) as _rank
               from sc
                        left join student as s
                                  on sc.s_id =s.s_id) as rt
where rt._rank <=3;

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

select  c.c_id, count(sc.s_id) as num
from course as c
left join sc on c.c_id =sc.c_id
group by c.c_id;

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

# 方法1:(1)查询每个学生选得课的课程数
select s_id ,count(c_id)
from sc
group by s_id;

# (2)过滤中课数为2的学生并连接学生查询学生信息
select * from student as s
where s.s_id in(
    select sc.s_id
    from sc
    group by sc.s_id
    having count(sc.c_id) =2
    );
# 方法2: 先连接学生和中间表得到全部学生的选得全部课程,然后按照学生分组,过滤出课程数为2的学生
select s.s_id,s.s_name,s.s_age,s.s_sex
from student as s
left join  sc on s.s_id =sc.s_id
group by s.s_id,s.s_name,s.s_sex,s.s_age
having count(sc.c_id) =2;

28.查询男生、女生人数

select  s_sex,count(*) from student
group by s_sex;

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

select *
from student
where s_name like '%三%'

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

# (1)按照姓名、性别分组,可得到学生以及人数
select s_name,s_sex,count(*) as count
from student as s
group by s.s_name,s.s_sex
having count(*)>1;
# (2)以姓名性别为条件,把(1)连接学生表,查询对应学生记录
select s2.*,temp.count from student as s2
   inner  join  (select s_name,s_sex,count(*) as count
                 from student as s
                 group by s.s_name,s.s_sex
                 having count(*)>1) as temp
           on s2.s_name =temp.s_name and s2.s_sex =temp.s_sex;

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

select *
from student where  date_format(s_age,'%Y') =1990;

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

select sc.s_id, s.s_name, round(avg(score),1) as  avg_score from sc
inner join  student as s  on s.s_id  =sc.s_id
group by sc.s_id, s.s_name
having avg(sc.score)>=85;

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

select c_id,round(avg(score),1)  as avg_score
from sc
group by c_id
order by  avg_score asc,c_id desc;

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

select s.s_name,sc.score
from student as s
inner  join sc on s.s_id =sc.s_id
inner  join course as c on c.c_id = sc.c_id
where c.c_name ='数学' and sc.score <60;

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

select s.s_id,s.s_name,c.*,sc.score
from student as s
         left  join sc on s.s_id =sc.s_id
         left  join course as c on c.c_id = sc.c_id;

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

select s.s_name,c.c_name, sc.score
from student as s
         inner  join sc on s.s_id =sc.s_id
         inner  join course as c on c.c_id = sc.c_id
where sc.score>70;

37.查询不及格的课程并按课程号从大到小排列

select c.* from course  as c
  left join sc   on c.c_id = sc.c_id
where sc.score<60
order by  c.c_id desc;

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

select s.s_id,s_name from student as s
inner  join  sc on s.s_id = sc.s_id
where sc.c_id ='03' and sc.score>80;

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

select  c_id ,count(s_id) as count from sc
group by c_id;

40.查询选修“张三”老师所授课程的学生中成绩最高的学生姓名及其成绩

select  s.s_name,sc.score
from student as s
         inner  join sc on s.s_id =sc.s_id
where sc.score in  (select max(sc.score)
                    from student as s
                             inner  join sc on s.s_id =sc.s_id
                             inner  join course as c on c.c_id = sc.c_id
                             inner  join  teacher as t on t.t_id =c.t_id
                    where t.t_name='张三'
                    group by c.c_id);

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

# (1)查询不同课程但成绩相同的课程编号、学生成绩
select c_id ,score from sc
group by c_id,score
having COUNT(score)>1;
# (2)查询所求
select * from sc where (c_id,score) in (select c_id ,score from sc
                                        group by c_id,score
                                        having COUNT(score)>1);

42.查询每一门课程最好的前两名

# (1)按照课程分区,查询全部排名
select s.s_id,s.s_name ,sc.score ,dense_rank() over (partition by sc.c_id order by  sc.score desc) as _rank
from student as s
inner join  sc  on s.s_id =sc.s_id
# (2)过滤出前2名
select *
from (select sc.c_id ,s.s_id,s.s_name ,sc.score ,dense_rank() over (partition by sc.c_id order by  sc.score desc) as _rank
      from student as s
               inner join  sc  on s.s_id =sc.s_id)rn
where rn._rank<=2;

43.统计每门课程的学生选修人数(超过5人的课程才统计)。

要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列

select c_id, count(s_id) as count from sc
group by c_id
having count >5
order by count desc  ,c_id asc;

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

select s_id,count(c_id)
from sc
group by  s_id
having count(c_id)>=2;

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

# (1)查询全部课程的个数
select count(*)
from course;
# (2)查询选修全部个数学生
select s.s_id,s.s_name,s.s_age,s.s_sex,count(*) as num
from sc
left join  student as s  on s.s_id =sc.s_id
group by s.s_id,s.s_name,s.s_age,s.s_sex
having num =(select count(*)
                  from course);

46.查询各学生的年龄

# 方法1
select  s_id,  DATE_FORMAT(now(),'%Y') -DATE_FORMAT(s_age,'%Y') as age
from student;
# 方法2
select  s_id,  TIMESTAMPDIFF(YEAR,s_age,now() ) as age
from student;

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

select * from student
where s_age between SUBDATE(now(),DATE_FORMAT(s_age,'%w')-1) and ADDDATE(now(),7-DATE_FORMAT(s_age,'%w'));

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

select * from student
where s_age between ADDDATE(now(),DATE_FORMAT(s_age,'%w')+1) and ADDDATE(now(),7-DATE_FORMAT(s_age,'%w')+7);

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

select * from student  where DATE_FORMAT(s_age,'%m') =DATE_FORMAT(now(),'%m');

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

select * from student  where DATE_FORMAT(s_age,'%m') = DATE_FORMAT(TIMESTAMPADD(MONTH ,1,now()),'%m');

注解

1.union all是合并结果集(但 不去重,想要去重用union,性能没有union高),如1题
2.format 将数值格式化字符串,并保留几位。如18题
3.nullif(表达式1,表达式2)如果表达式相等,返回null ,不相等就返回第一个表达式 。可防止被零整除。如18题
4.coalesce(值1,值2,值…) 返回第一个非空值 ,如果都为空,则返回空。如19题
5.(1)row_number() over (order by sum(列) ) 根据指定列排序,并可以得到行的序号,如果值相同,序号不会并列。如20题
(2)rank() over () 类似row_number
但如果值相同,会并列排名,下一个会跳过这个排名(如并列第一 下一个第三)
(3)ENSE_RANK():与 RANK()
类似,但是不会跳过排名(例如,如果两行并列第一,则下一个排名是第二)。如22题
(4)partition by 定义窗口函数的分区
(5)over 定义窗口函数的操作,定义窗口函数的范围以及排序,决定窗口函数的功能

猜你喜欢

转载自blog.csdn.net/pursuedream6/article/details/139790254