zoukankan      html  css  js  c++  java
  • MySQL SQL Training

      源于知乎:50道SQL练习题

    一、表数据

      1、学生表——Student

    create table Student(SId varchar(10),Sname varchar(10),Sage datetime,Ssex varchar(10));
    insert into Student values('01' , '赵雷' , '1990-01-01' , '');
    insert into Student values('02' , '钱电' , '1990-12-21' , '');
    insert into Student values('03' , '孙风' , '1990-05-20' , '');
    insert into Student values('04' , '李云' , '1990-08-06' , '');
    insert into Student values('05' , '周梅' , '1991-12-01' , '');
    insert into Student values('06' , '吴兰' , '1992-03-01' , '');
    insert into Student values('07' , '郑竹' , '1989-07-01' , '');
    insert into Student values('09' , '张三' , '2017-12-20' , '');
    insert into Student values('10' , '李四' , '2017-12-25' , '');
    insert into Student values('11' , '李四' , '2017-12-30' , '');
    insert into Student values('12' , '赵六' , '2017-01-01' , '');
    insert into Student values('13' , '孙七' , '2018-01-01' , '');

      2、科目表——Course

    create table Course(CId varchar(10),Cname nvarchar(10),TId varchar(10))
    insert into Course values('01' , '语文' , '02');
    insert into Course values('02' , '数学' , '01');
    insert into Course values('03' , '英语' , '03');

      3、教师表——Teacher

    create table Teacher(TId varchar(10),Tname varchar(10))
    insert into Teacher values('01' , '张三');
    insert into Teacher values('02' , '李四');
    insert into Teacher values('03' , '王五');

      4、成绩表——SC

    create table SC(SId varchar(10),CId varchar(10),score decimal(18,1));
    insert into SC values('01' , '01' , 80);
    insert into SC values('01' , '02' , 90);
    insert into SC values('01' , '03' , 99);
    insert into SC values('02' , '01' , 70);
    insert into SC values('02' , '02' , 60);
    insert into SC values('02' , '03' , 80);
    insert into SC values('03' , '01' , 80);
    insert into SC values('03' , '02' , 80);
    insert into SC values('03' , '03' , 80);
    insert into SC values('04' , '01' , 50);
    insert into SC values('04' , '02' , 30);
    insert into SC values('04' , '03' , 20);
    insert into SC values('05' , '01' , 76);
    insert into SC values('05' , '02' , 87);
    insert into SC values('06' , '01' , 31);
    insert into SC values('06' , '03' , 34);
    insert into SC values('07' , '02' , 89);
    insert into SC values('07' , '03' , 98);

    二、SQL练习题

    1. 查询同时存在" 01 "课程和" 02 "课程的情况

    /*只列出学生ID和课程情况*/
    select t1.SId,t1.score as score01,t2.score as score02 
    from (select SId,score from sc where CId='01') as t1,
        (select SId, score from sc   where CId='02') as t2 
    where t1.SId=t2.SId;
    
    +------+---------+---------+
    | SId  | score01 | score02 |
    +------+---------+---------+
    | 01   |    80.0 |    90.0 |
    | 02   |    70.0 |    60.0 |
    | 03   |    80.0 |    80.0 |
    | 04   |    50.0 |    30.0 |
    | 05   |    76.0 |    87.0 |
    +------+---------+---------+
    5 rows in set (0.00 sec)

      改进一下:

    select sc1.sid,sc1.cid cid01,sc1.score score01,sc2.cid cid02,sc2.score score02
    from sc sc1 join sc sc2 
    on sc1.sid=sc2.sid and sc1.cid="01" and sc2.cid="02";
    
    +------+-------+---------+-------+---------+
    | sid  | cid01 | score01 | cid02 | score02 |
    +------+-------+---------+-------+---------+
    | 01   | 01    |    80.0 | 02    |    90.0 |
    | 02   | 01    |    70.0 | 02    |    60.0 |
    | 03   | 01    |    80.0 | 02    |    80.0 |
    | 04   | 01    |    50.0 | 02    |    30.0 |
    | 05   | 01    |    76.0 | 02    |    87.0 |
    +------+-------+---------+-------+---------+
    5 rows in set (0.00 sec)

      如果在此基础上列出更多关于学生的信息:

    /*同时列出相关学生的信息*/
    select t1.SId,t1.score as score01,t2.score as score02,t3.* 
    from (select SId,score from sc where CId='01') as t1,
        (select SId, score from sc where CId='02') as t2,
        Student as t3 
    where t1.SId=t2.SId and t1.SId=t3.SId;
    
    +------+---------+---------+------+-------+---------------------+------+
    | SId  | score01 | score02 | SId  | Sname | Sage                | Ssex |
    +------+---------+---------+------+-------+---------------------+------+
    | 01   |    80.0 |    90.0 | 01   | 赵雷  | 1990-01-01 00:00:00 ||
    | 02   |    70.0 |    60.0 | 02   | 钱电  | 1990-12-21 00:00:00 ||
    | 03   |    80.0 |    80.0 | 03   | 孙风  | 1990-05-20 00:00:00 ||
    | 04   |    50.0 |    30.0 | 04   | 李云  | 1990-08-06 00:00:00 ||
    | 05   |    76.0 |    87.0 | 05   | 周梅  | 1991-12-01 00:00:00 ||
    +------+---------+---------+------+-------+---------------------+------+
    5 rows in set (0.00 sec)

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

      在“同时存在01课程和02课程”的基础上,添加一个条件即可:

    select t1.SId,t1.score as score01,t2.score as score02,t3.* 
    from (select SId,score from sc where CId='01') as t1,(select SId, score from sc where CId='02') as t2,Student as t3
    where t1.SId=t2.SId and t1.score>t2.score and t1.SId=t3.SId; +------+---------+---------+------+-------+---------------------+------+ | SId | score01 | score02 | SId | Sname | Sage | Ssex | +------+---------+---------+------+-------+---------------------+------+ | 02 | 70.0 | 60.0 | 02 | 钱电 | 1990-12-21 00:00:00 || | 04 | 50.0 | 30.0 | 04 | 李云 | 1990-08-06 00:00:00 || +------+---------+---------+------+-------+---------------------+------+ 2 rows in set (0.00 sec)

     

    1.2 查询存在" 01 "课程但可能不存在" 02 "课程的情况(不存在时显示为 null )

    /*只列出学生ID*/
    select * from (select SId ,score from sc where sc.CId='01')as t1 
        left join  (select SId ,score from sc where sc.CId='02') as t2 on t1.SId=t2.SId;
    
    /*列出学生具体信息*/
    select t1.SId,t1.score as score01,t2.score as score02,t3.* from (select SId,score 
        from sc where CId='01') as t1 left join (select SId, score from sc where CId='02') as t2 on  t1.SId=t2.SId,Student as t3 
            where t1.SId=t3.SId;
    View Code

      结果如下:

    1.3 查询不存在" 01 "课程但存在" 02 "课程的情况

    select * from sc 
        where SId not in (select Sid from sc where CId='01') and CId='02';

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

    /*第一种*/
    select t1.SId,t2.Sname,t1.avg 
        from (select SId,AVG(score) as avg from sc group by SId having avg>=60) as t1,student as t2 
            where t1.SId=t2.SId;
    
    
    /*第二种*/
    select student.*,t1.avgscore 
        from student 
            inner JOIN( select sc.SId ,AVG(sc.score)as avgscore from sc GROUP BY sc.SId HAVING AVG(sc.score)>=60)as t1 on student.SId=t1.SId;

    3. 查询在 SC 表存在成绩的学生信息

    /*第一种*/
    select * from Student where SId in (Select SId from sc group by SId);
    
    /*第二种*/
    select DISTINCT student.* from student ,sc where student.SId=sc.SId;
    
    /*第三种*/
    select * from Student where SId in (Select DISTINCT SId from sc);

    4. 查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩(没成绩的显示为 null )

    /*第一种*/
    select stu.SId,stu.Sname,t1.NumCourse,t1.SumCourse 
        from Student as stu left join (select SId, count(CId) as NumCourse,sum(score) as SumCourse from sc group by SId) as t1 
            on stu.SId=t1.SId;

    4.1 查看有成绩的学生信息

    /*第一种*/
     select * from student where SId in (select distinct SId from sc);
    
    /*第二种*/
    select * from student where EXISTS(select * from sc where student.SId=sc.SId);

    5. 查询「李」姓老师的数量

    /*第一种*/
    select count(*) from teacher where Tname like "李%";

    6. 查询学过「张三」老师授课的同学的信息

    /*第一种,嵌套查询,略复杂*/
     select * from Student 
        where SId in 
            (select SId from sc where CId in 
                (select course.CId from course,teacher where course.TId=teacher.TId and teacher.Tname="张三"));
    
    /*第二种*/
    select student.* from teacher  ,course  ,student,sc 
        where teacher.Tname='张三' and   teacher.TId=course.TId 
            and   course.CId=sc.CId and   sc.SId=student.SId;

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

    /*第一种*/
    /*先找出休全了所有课的学生的ID*/
    select * from student 
      where SId not in (
          select SId from sc group by SId having count(CId)=(select count(CId) from course));

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

    /*第一种*/
    /*01号学生列不列都可以*/
    select * from student 
    where SId in 
        (select distinct SId from sc where CId in 
            (select distinct CId from sc where SId="01") and SId!="01") ;

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

    /*第一种*/
    /*sql过长的原因在于,同一个子查询(即t1,t2是同一个子查询),我不得不写两遍,没有找到好的解决方法*/
    select * from student 
    where SId!="01" and SId in (
        select t1.SId 
        from (
            select SId,group_concat(CId order by CId desc) allcourse 
            from sc 
            group by SId 
            order by SId asc
        ) as t1 
        where md5(t1.allcourse)=(
            select md5(t2.allcourse2) 
            from (
                select SId,group_concat(CId order by CId desc) allcourse2 
                from sc 
                group by SId 
                order by SId asc
            ) as t2 
            where SId="01"
        )
    ) 
     
    
     /*第二种*/
    select * from student 
    where student.SId !='01'and student.SId not in (
        select t1.SId 
        from (
            select student.SId,t.CId 
            from student ,(select sc.CId from sc where sc.SId='01') as t )as t1 
            left join sc 
            on t1.SId=sc.SId and t1.CId=sc.CId 
            where sc.CId is null 
    ); 
    
    +------+-------+---------------------+------+
    | SId  | Sname | Sage                | Ssex |
    +------+-------+---------------------+------+
    | 02   | 钱电  | 1990-12-21 00:00:00 ||
    | 03   | 孙风  | 1990-05-20 00:00:00 ||
    | 04   | 李云  | 1990-08-06 00:00:00 ||
    +------+-------+---------------------+------+
    3 rows in set (0.00 sec)

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

    /*第一种*/
    select distinct * from student as stu 
        where stu.SId not in (
            select SId from sc where CId in (select CId from course where TId=(
                select TId from teacher where Tname="张三"))) ;
    
    /*第二种*/
    select *
    from student 
    where student.SId not in (
        select student.SId
        from student left join sc on student.SId=sc.SId 
        where EXISTS (
            select *
            from teacher ,course
            where teacher.Tname='张三' and teacher.TId=course.TId and course.CId=sc.CId
        )
    )

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

    /*第一种*/
    select t.SId,student.Sname,t.avgScore 
    from student,(select SId,count(CId) as numCourse,avg(score) as avgScore from sc where score<60 group by SId) as t 
    where t.SId=student.SId and numCourse>=2;
    
    /*第二种*/
    select student.SId,student.Sname,avg(sc.score) 
    from student ,sc 
    where student.SId=sc.SId and sc.score<60 GROUP BY sc.SId HAVING count(*)>=2;

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

    select stu.*,sc.score 
    from student stu,sc 
    where stu.SId=sc.SId and CId="01" and score<60 order by score desc;

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

    /*第一种*/
    /*这里在order前加不加group by,结果都一样*/
    select sc.*,t.avg 
    from sc ,(select SId,avg(score) avg from sc group by SId) as t 
    where sc.SId=t.SId 
    order by t.avg desc;
    
    /*第二种*/
    select sc.SId,sc.CId,sc.score,t1.avgscore 
    from  sc left join (select sc.SId,avg(sc.score) as avgscore from sc GROUP BY sc.SId) as t1 on sc.SId =t1.SId 
    ORDER BY t1.avgscore DESC;

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

      以如下形式显示:

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

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

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

    /*注意group by,order by的位置,很困惑,与select要对应*/
    select sc.CId ,co.Cname,
        max(sc.score)as 最高分,
        min(sc.score)as 最低分,AVG(sc.score)as 平均分,
        count(*)as 选修人数,sum(case when sc.score>=60 then 1 else 0 end )/count(*)as 及格率,
        sum(case when sc.score>=70 and sc.score<80 then 1 else 0 end )/count(*)as 中等率,
        sum(case when sc.score>=80 and sc.score<90 and sc.score<80 then 1 else 0 end )/count(*)as 优良率,
        sum(case when sc.score>=90 then 1 else 0 end )/count(*)as 优秀率 
    from sc
    left join course as co on sc.CId=co.CId
    GROUP BY sc.CId
    ORDER BY count(*)DESC,sc.CId asc

    15. 按各科成绩进行排序,并显示排名。(三种形式都来一遍)(此时我新添加了2个学生的各三门成绩)

      15.1 相同的score,rank不重复,按sid排名。所有的rank是连续的。(1,2,3)

      from中的t表是为了变量初始化而无需单独的SET命令。

      第二个when的条件总是true。

    select sc.SId,sc.CId,sc.score,
        case 
            when @pre_parent_code=sc.CId then @curRank:=@curRank+1 
            when @pre_parent_code:=sc.CId then  @curRank:=1  
        end as rank
    from (select @curRank:=0,@pre_parent_code:='') as t ,sc 
    ORDER by sc.CId,sc.score desc;
    
    +------+------+-------+------+
    | SId  | CId  | score | rank |
    +------+------+-------+------+
    | 01   | 01   |  80.0 |    1 |
    | 03   | 01   |  80.0 |    2 |
    | 05   | 01   |  76.0 |    3 |
    | 02   | 01   |  70.0 |    4 |
    | 09   | 01   |  70.0 |    5 |
    | 04   | 01   |  50.0 |    6 |
    | 06   | 01   |  31.0 |    7 |
    | 10   | 01   |  31.0 |    8 |
    | 01   | 02   |  90.0 |    1 |
    | 10   | 02   |  90.0 |    2 |
    | 07   | 02   |  89.0 |    3 |
    | 05   | 02   |  87.0 |    4 |
    | 03   | 02   |  80.0 |    5 |
    | 02   | 02   |  60.0 |    6 |
    | 04   | 02   |  30.0 |    7 |
    | 09   | 02   |  30.0 |    8 |
    | 01   | 03   |  99.0 |    1 |
    | 09   | 03   |  99.0 |    2 |
    | 07   | 03   |  98.0 |    3 |
    | 02   | 03   |  80.0 |    4 |
    | 03   | 03   |  80.0 |    5 |
    | 06   | 03   |  34.0 |    6 |
    | 04   | 03   |  20.0 |    7 |
    | 10   | 03   |  20.0 |    8 |
    +------+------+-------+------+
    24 rows in set (0.00 sec)

      15.2 相同的Score,rank相同,而且所有rank是有间断的(例如第一和第二分数相同,那么前三名的rank为1,1,3)

      这种排序应该是实际中会采纳的排序。

      这种形式的排序比较好理解,self-join,找出另一个表中同组中值比自己大的行数,那自己的排名就是count+1,间断也是自动产生了。

    select sc.SId,sc.CId,sc.score,tp.rank
    from sc 
    left join (select SId, CId, (select count(sc2.score)+1 from sc sc2 where sc1.CId=sc2.CId and sc2.score>sc1.score) rank from sc sc1) tp
    on sc.SId=tp.SId and sc.CId=tp.CId
    order by sc.CId, rank
    
    +------+------+-------+------+
    | SId  | CId  | score | rank |
    +------+------+-------+------+
    | 01   | 01   |  80.0 |    1 |
    | 03   | 01   |  80.0 |    1 |
    | 05   | 01   |  76.0 |    3 |
    | 02   | 01   |  70.0 |    4 |
    | 09   | 01   |  70.0 |    4 |
    | 04   | 01   |  50.0 |    6 |
    | 06   | 01   |  31.0 |    7 |
    | 10   | 01   |  31.0 |    7 |
    | 01   | 02   |  90.0 |    1 |
    | 10   | 02   |  90.0 |    1 |
    | 07   | 02   |  89.0 |    3 |
    | 05   | 02   |  87.0 |    4 |
    | 03   | 02   |  80.0 |    5 |
    | 02   | 02   |  60.0 |    6 |
    | 04   | 02   |  30.0 |    7 |
    | 09   | 02   |  30.0 |    7 |
    | 01   | 03   |  99.0 |    1 |
    | 09   | 03   |  99.0 |    1 |
    | 07   | 03   |  98.0 |    3 |
    | 02   | 03   |  80.0 |    4 |
    | 03   | 03   |  80.0 |    4 |
    | 06   | 03   |  34.0 |    6 |
    | 04   | 03   |  20.0 |    7 |
    | 10   | 03   |  20.0 |    7 |
    +------+------+-------+------+
    24 rows in set (0.00 sec)

       经过自己对其它的参考,竟然改出一个简单的版本:

    select sc2.sid as sid,sc2.cid as cid,sc2.score,if(isnull(sc3.score),1,count(*)+1) as rank 
    from sc sc2 left join sc sc3 
    on sc3.CId=sc2.CId and sc2.score<sc3.score 
    group by sc2.cid,sc2.sid
    order by cid,score desc;
    /*相比其它,我新插入了两个学生的供6条成绩*/
    +------+------+-------+------+ | sid | cid | score | rank | +------+------+-------+------+ | 01 | 01 | 80.0 | 1 | | 03 | 01 | 80.0 | 1 | | 05 | 01 | 76.0 | 3 | | 02 | 01 | 70.0 | 4 | | 09 | 01 | 70.0 | 4 | | 04 | 01 | 50.0 | 6 | | 06 | 01 | 31.0 | 7 | | 10 | 01 | 31.0 | 7 | | 01 | 02 | 90.0 | 1 | | 10 | 02 | 90.0 | 1 | | 07 | 02 | 89.0 | 3 | | 05 | 02 | 87.0 | 4 | | 03 | 02 | 80.0 | 5 | | 02 | 02 | 60.0 | 6 | | 04 | 02 | 30.0 | 7 | | 09 | 02 | 30.0 | 7 | | 09 | 03 | 99.0 | 1 | | 01 | 03 | 99.0 | 1 | | 07 | 03 | 98.0 | 3 | | 02 | 03 | 80.0 | 4 | | 03 | 03 | 80.0 | 4 | | 06 | 03 | 34.0 | 6 | | 04 | 03 | 20.0 | 7 | | 10 | 03 | 20.0 | 7 | +------+------+-------+------+ 24 rows in set (0.00 sec)

    15.3 相同的Score,rank相同,但是所有rank连续(第一第二分数相同,前四名1,1,2,3)

      首先,这种排序是不科学的。

      方法就是在上一题的基础上,在进行self-join时,添加"distinct",去重即可。比如第三名,因为统计时有两个值比自己大,但是不管有几个相同的值比自己大,自己的rank都是2,用count(distinct col)+1就可以做到。

    /*001*/
    select sc.SId,sc.CId,sc.score,tp.rank
    from sc 
    left join (
        select SId, CId, (
            select count(distinct sc2.score)+1
            from sc sc2
            where sc1.CId=sc2.CId and sc2.score>sc1.score
            ) rank
        from sc sc1
        ) tp
    on sc.SId=tp.SId and sc.CId=tp.CId
    order by sc.CId, rank
    
    /*002*/
    select sc2.sid as sid,sc2.cid as cid,sc2.score,if(isnull(sc3.score),1,count(distinct sc3.score)+1) as rank 
    from sc sc2 left join sc sc3 
    on sc3.CId=sc2.CId and sc2.score<sc3.score 
    group by sc2.cid,sc2.sid
    order by cid,score desc;
    
    +------+------+-------+------+
    | sid  | cid  | score | rank |
    +------+------+-------+------+
    | 03   | 01   |  80.0 |    1 |
    | 01   | 01   |  80.0 |    1 |
    | 05   | 01   |  76.0 |    2 |
    | 09   | 01   |  70.0 |    3 |
    | 02   | 01   |  70.0 |    3 |
    | 04   | 01   |  50.0 |    4 |
    | 06   | 01   |  31.0 |    5 |
    | 10   | 01   |  31.0 |    5 |
    | 01   | 02   |  90.0 |    1 |
    | 10   | 02   |  90.0 |    1 |
    | 07   | 02   |  89.0 |    2 |
    | 05   | 02   |  87.0 |    3 |
    | 03   | 02   |  80.0 |    4 |
    | 02   | 02   |  60.0 |    5 |
    | 04   | 02   |  30.0 |    6 |
    | 09   | 02   |  30.0 |    6 |
    | 01   | 03   |  99.0 |    1 |
    | 09   | 03   |  99.0 |    1 |
    | 07   | 03   |  98.0 |    2 |
    | 02   | 03   |  80.0 |    3 |
    | 03   | 03   |  80.0 |    3 |
    | 06   | 03   |  34.0 |    4 |
    | 10   | 03   |  20.0 |    5 |
    | 04   | 03   |  20.0 |    5 |
    +------+------+-------+------+
    24 rows in set (0.00 sec)

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

    select sc1.sid,sc1.sum,if(isnull(sc2.sum),1,count(sc2.sum)+1) rank
    from (select sid,sum(score) as sum from sc group by sid) as sc1
    left join (select sid,sum(score) as sum from sc group by sid) as sc2
    on sc1.sum<sc2.sum
    group by sc1.sid
    order by rank asc
    
    +------+-------+------+
    | sid  | sum   | rank |
    +------+-------+------+
    | 01   | 269.0 |    1 |
    | 03   | 240.0 |    2 |
    | 02   | 210.0 |    3 |
    | 09   | 199.0 |    4 |
    | 07   | 187.0 |    5 |
    | 05   | 163.0 |    6 |
    | 10   | 141.0 |    7 |
    | 04   | 100.0 |    8 |
    | 06   |  65.0 |    9 |
    +------+-------+------+
    9 rows in set (0.00 sec)

    16.1 查询学生的总成绩,并进行排名,总分重复时不保留名次空缺(1,1,2)

       在上题基础上添加distinct即可。

    select sc1.sid,sc1.sum,if(isnull(sc2.sum),1,count(distinct sc2.sum)+1) rank
    from (select sid,sum(score) as sum from sc group by sid) as sc1
    left join (select sid,sum(score) as sum from sc group by sid) as sc2
    on sc1.sum<sc2.sum
    group by sc1.sid
    order by rank asc

    (因为上几道排序的题,我在成绩表中添加了6行新的数据,这里再改回去,原表只有18行)

    rename table sc to st; 
    rename table scback to sc;

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

    select course.CId,course.Cname,t1.*
    from course LEFT JOIN (
        select sc.CId,
            sum(case when sc.score>=85 and sc.score<=100 then 1 else 0 end ) as '[85-100] Number',
            CONCAT(sum(case when sc.score>=85 and sc.score<=100 then 1 else 0 end )/count(*)*100,'%') as '[85-100]',
    
            sum(case when sc.score>=70 and sc.score<85 then 1 else 0 end ) as '[70-85) Number',
            CONCAT(sum(case when sc.score>=70 and sc.score<85 then 1 else 0 end )/count(*)*100,'%') as '[70-85)',
    
            sum(case when sc.score>=60 and sc.score<70 then 1 else 0 end ) '[60-70) Number',
            CONCAT(sum(case when sc.score>=60 and sc.score<70 then 1 else 0 end )/count(*)*100,'%') as '[60-70)',
    
            sum(case when sc.score>=0 and sc.score<60 then 1 else 0 end ) as '[0-60) Number',
            CONCAT(sum(case when sc.score>=0 and sc.score<60 then 1 else 0 end )/count(*)*100,'%') as '[0-60)'
        from sc
        GROUP BY sc.CId
    ) as t1 
    on course.CId=t1.CId

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

      这里的前三名,有一定的歧义:

      如果某科成绩如“100,100,95,95,90,90,88,...”,前三名是应该是指成绩为90,95,100的人6个学生?还是只有“100,90”的4个?

      如果某科成绩为““100,100,100,95,95,90,90,88,...”,前三名是成绩为100的3个学生?还是成绩为“100,95,90”的7个学生?

    select CId, SId, score
    from sc
    where (select count(*) from sc sc1 where sc1.CId=sc.CId and sc1.score>sc.score) <3
    order by CId, score desc

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

    select course.*,t.count 
    from course 
    left join (select cid,count(sid) as count from sc group by cid) as t 
    on course.cid=t.cid;

    20. 查询出只选修两门课程的学生学号和姓名

    select sid,sname 
    from student 
    where sid in(select sid from sc group by sid having count(cid)=2);

    21. 查询男生、女生人数

     select ssex,count(sid) from student group by ssex;

    22. 查询名字中含有「风」字的学生信息

    select * from student where sname like'%风%';

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

    select s.sid,s.sname,s.ssex,count(*) 
    from student as s 
    join student as t 
    on s.sname=t.sname and s.ssex=t.ssex and s.sid!=t.sid 
    group by sid with rollup;
    
    
    +------+-------+------+----------+
    | sid  | sname | ssex | count(*) |
    +------+-------+------+----------+
    | 10   | 李四  ||        1 |
    | 11   | 李四  ||        1 |
    | NULL | 李四  ||        2 |
    +------+-------+------+----------+

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

    select * from student where year(sage)=1990;

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

    select cid, avg(score) as avg 
    from sc 
    group by cid order by avg desc;
    
    +------+----------+
    | cid  | avg      |
    +------+----------+
    | 02   | 72.66667 |
    | 03   | 68.50000 |
    | 01   | 64.50000 |
    +------+----------+
    
    
    
    select c.*,t.avg as avg 
    from course as c 
    join (select cid, avg(score) as avg from sc group by cid) as t 
    on c.cid=t.cid 
    order by avg desc,cid;
    
    +------+-------+------+----------+
    | CId  | Cname | TId  | avg      |
    +------+-------+------+----------+
    | 02   | 数学  | 01   | 72.66667 |
    | 03   | 英语  | 03   | 68.50000 |
    | 01   | 语文  | 02   | 64.50000 |
    +------+-------+------+----------+

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

    select stu.* 
    from student as stu 
    where sid in (select sid from sc group by sid having avg(score)>=85);
    
    +------+-------+---------------------+------+
    | SId  | Sname | Sage                | Ssex |
    +------+-------+---------------------+------+
    | 01   | 赵雷  | 1990-01-01 00:00:00 ||
    | 07   | 郑竹  | 1989-07-01 00:00:00 ||
    +------+-------+---------------------+------+
    
    select stu.*,t.score 
    from student as stu,
        (select sid,avg(score) as score from sc group by sid having avg(score)>=85) as t 
    where stu.sid=t.sid;
    
    +------+-------+---------------------+------+----------+
    | SId | Sname | Sage | Ssex | score |
    +------+-------+---------------------+------+----------+
    | 01 | 赵雷 | 1990-01-01 00:00:00 || 89.66667 |
    | 07 | 郑竹 | 1989-07-01 00:00:00 || 93.50000 |
    +------+-------+---------------------+------+----------+

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

    select sid,sname 
    from student 
    where sid in (
        select sid 
        from sc 
        where cid in (
            select cid from course where cname="数学"
      ) and score<60
    ); +------+-------+ | sid | sname | +------+-------+ | 04 | 李云 | +------+-------+ 1 row in set (0.00 sec)

    28. 查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)

    select s.sid,s.sname,t.cid,t.score 
    from student as s 
    left join sc as t 
    on s.sid=t.sid 
    order by sid,cid;

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

    select t.sid,s.sname,c.cname,t.score 
    from sc as t,student as s,course as c 
    where t.score>70 and t.cid=c.cid and t.sid=s.sid;
    
    +------+-------+-------+-------+
    | sid  | sname | cname | score |
    +------+-------+-------+-------+
    | 01   | 赵雷  | 语文  |  80.0 |
    | 01   | 赵雷  | 数学  |  90.0 |
    | 01   | 赵雷  | 英语  |  99.0 |
    | 02   | 钱电  | 英语  |  80.0 |
    | 03   | 孙风  | 语文  |  80.0 |
    | 03   | 孙风  | 数学  |  80.0 |
    | 03   | 孙风  | 英语  |  80.0 |
    | 05   | 周梅  | 语文  |  76.0 |
    | 05   | 周梅  | 数学  |  87.0 |
    | 07   | 郑竹  | 数学  |  89.0 |
    | 07   | 郑竹  | 英语  |  98.0 |
    +------+-------+-------+-------+

    30. 查询不及格的课程(什么意思?平均分不及格?)

    select cid,avg(score) from sc group by cid having avg(score)<60;

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

    select sid,sname from student
    where sid in(
        select sid from sc where cid=01 and score>80
    );

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

    select cid ,count(sid) from sc group by cid;

    33. 成绩不重复,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩

      这里有多种情况需要考虑。

      第一是一个老师只开一门课,那这课最高的分数只会有一个:

    /*由于一个老师只开一门课,这里的in可以用=替换*/
    select
    * from sc where cid in (select cid from course where tid=(select tid from teacher where tname="张三") ) order by score desc limit 1; +------+------+-------+ | SId | CId | score | +------+------+-------+ | 01 | 02 | 90.0 | +------+------+-------+ 1 row in set (0.00 sec)

      骑士这里利用排序和LIMIT来输出是不对的,如果最高成绩有多名学生,那就错了,所以还是要从对cid分组入手,利用max函数找出该门课的最高分,再在成绩表中进行筛选。

      第二是一个老师可以开多门课,那每一门课都会存在一个最高成绩,如果只是输出多门课中的一个最高成绩,那语句与上面情况一样(只是in不能用=替换)。

      而如果是每一门课的最高成绩都输出,那么在成绩表sc中找出这个老师的所有课的成绩记录,然后对这个派生表用cid分组,并找出他的每门课的max(score),然后再从成绩表sc入手找出cid相等,score=max(score)的记录。最后连接student表,输出信息与成绩。

     

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

      上面已经讨论过了!

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

      这里应该是指同一个学生有不同的课程成绩相同。

    select distinct sc.* 
    from sc 
    join sc as t 
    on sc.sid=t.sid and sc.cid!=t.cid and sc.score=t.score;

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

      (这个取“前两名”可以利用排序和LIMIT解决了)

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

    select cid, count(sid) as number 
    from sc 
    group by cid 
    having count(sid)>5;
    
    +------+--------+
    | cid  | number |
    +------+--------+
    | 01   |      6 |
    | 02   |      6 |
    | 03   |      6 |
    +------+--------+
    3 rows in set (0.00 sec)

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

    select sid ,count(cid) as cNum 
    from sc 
    group by sid 
    having cNum>1;

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

    /*先查询总共共有多少门课*/
    select count(distinct cid) from course;
    
    +---------------------+
    | count(distinct cid) |
    +---------------------+
    |                   3 |
    +---------------------+
    
    /*从成绩表找出满足条件的sid*/
    select sid 
    from sc group by sid 
    having count(cid)=(select count(distinct cid) from course);
    +------+
    | sid  |
    +------+
    | 01   |
    | 02   |
    | 03   |
    | 04   |
    +------+
    4 rows in set (0.00 sec)

    40. 查询各学生的年龄,只按年份来算

    select sid,sname,year(curdate())-year(sage) from student;

    41. 按照出生日期来算,当前月日 < 出生年月的月日则,年龄减一

    select student.SId,student.Sname,TIMESTAMPDIFF(YEAR,student.Sage,CURDATE()) as age
    from student;

      关于时间函数 TIMESTAMPDIFF(unit,datetime_expr1,datetime_expr2)

       这里设置减法计算(expr2-expr1)后的unit为year,结果正好是符号题目的要求的

    SELECT TIMESTAMPDIFF(YEAR,'2000-05-05','2002-05-05') as result;
    +--------+
    | result |
    +--------+
    |      2 |
    +--------+
    
    SELECT TIMESTAMPDIFF(YEAR,'2000-05-05','2002-05-06')  as result;
    +--------+
    | result |
    +--------+
    |      2 |
    +--------+
    
    SELECT TIMESTAMPDIFF(YEAR,'2000-05-05','2002-05-04')  as result;
    +--------+
    | result |
    +--------+
    |      1 |
    +--------+

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

    select * from student where week(sage)=week(now());
    
    Empty set (0.00 sec)

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

    select * from student where week(sage)=week(now())+1;
    
    Empty set (0.00 sec)

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

    select * from student where month(sage)=month(now());
    Empty set (0.00 sec)

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

    select * from student where month(sage)=month(now())+1;
     
  • 相关阅读:
    单步调试理解webpack里通过require加载nodejs原生模块实现原理
    webpack打包过程如何调试?
    django-数据库之连接数据库
    django-模板之include标签(十五)
    django-模板之静态文件加载(十四)
    django-模板之过滤器Add(十三)
    django-模板之with标签(十二)
    django-模板之for empty(十一)
    django-模板之if语句(九)
    django-模板之自动转义autoescape(八)
  • 原文地址:https://www.cnblogs.com/bigbigbigo/p/10938356.html
Copyright © 2011-2022 走看看