程序员必修课--sql思维举重训练

    写sql是程序员基本功课,找工作面试一般必有sql题,实际工作中对sql的需求更是千变万化,所以掌握好sql对于一个程序员来说是件非常重要的事情.本文通过一个简单易懂的关系(学生/课程/成绩关系)尽量构造出各种各样的需求来提高我们写sql的功底,其中有些sql还是有一些难度的,大多数sql我都给出了思考思路,希望本人N天的劳动成果对您有所帮助.

    限于本人水平有限,有些地方的sql写的并不完美,希望大家不吝赐教.最后提一点小小的要求,希望大家对本文积极进行评论,大家的评论是我改进和提高的动力,我希望在和大家的交流中得到提高.

表关系:



建表和初始化sql(本例子使用oralce数据库):

--创建表
create table T_STUDENT(sno NUMBER not null,  sname VARCHAR2(30),  sdree VARCHAR2(50),  sage  NUMBER,  ssex  CHAR(2));
alter table T_STUDENT add primary key (SNO);
create table T_SCORE(sno   NUMBER,  cno   NUMBER,  grade NUMBER(4,1), tno NUMBER,  id NUMBER not null);
alter table T_SCORE add primary key (ID);
create table T_COURSE(cno NUMBER not null,  cname VARCHAR2(30));
alter table T_COURSE add primary key (CNO);

--初始化学生表
insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (1, '李坤', '天融信', 26, '男');
insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (2, '曹贵生', '中银', 26, '男');
insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (3, '柳波', '买卖宝', 27, '男');
insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (4, '纪争光', 'IBM', 23, '男');
insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (5, '李学宇', '微软', 25, '女');
insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (6, '李雪琪', '文思创新', 25, '女');
insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (7, '陈绪', '中海油', 26, '男');
insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (8, '韩正阳', '中海油', 24, '男');
insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (9, '陈伟东', '中核', 24, '男');
insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (10, '刘兵', '优酷', 24, '男');
insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (11, '丁成云', '联想', 25, '女');
insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (12, '王鹏', '中兴', 25, '男');
commit;

--初始化课程表
insert into T_COURSE (CNO, CNAME) values (1, 'JAVA程序设计');
insert into T_COURSE (CNO, CNAME) values (2, 'ORACLE开发');
insert into T_COURSE (CNO, CNAME) values (3, 'C++程序设计');
insert into T_COURSE (CNO, CNAME) values (4, 'C#程序设计');
insert into T_COURSE (CNO, CNAME) values (5, 'Windows实战');
insert into T_COURSE (CNO, CNAME) values (6, 'Center OS教程');
insert into T_COURSE (CNO, CNAME) values (7, 'Jsp/Servlet开发');
insert into T_COURSE (CNO, CNAME) values (8, 'J2EE从入门到精通');
insert into T_COURSE (CNO, CNAME) values (9, 'EJB及设计模式');
insert into T_COURSE (CNO, CNAME) values (10, 'Javascript/jQuery实战');
insert into T_COURSE (CNO, CNAME) values (11, 'Flash设计');
insert into T_COURSE (CNO, CNAME) values (12, 'HTML/CSS/JAVASCRIPT实战');
insert into T_COURSE (CNO, CNAME) values (13, '精通ASP.NET');
insert into T_COURSE (CNO, CNAME) values (14, 'JBoss入门');
insert into T_COURSE (CNO, CNAME) values (15, 'Spring开发');
commit;

--初始化成绩表
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (1, 2, 90.0, 2, 1);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (1, 3, 80.0, 3, 2);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (1, 4, 90.0, 4, 3);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 2, 70.0, 2, 4);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (2, 11, 66.0, 11, 5);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (2, 15, 77.0, 15, 6);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (2, 8, 87.0, 8, 7);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (2, 6, 96.0, 6, 8);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (3, 2, 89.0, 2, 9);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (3, 1, 91.0, 1, 10);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (4, 2, 83.0, 2, 11);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (5, 4, 73.0, 4, 12);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (5, 1, 60.0, 1, 13);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (5, 8, 82.0, 8, 14);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (6, 8, 90.5, 10, 15);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (8, 2, 58.0, 2, 16);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 3, 80.0, 3, 17);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (9, 11, 65.0, 11, 18);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (9, 12, 67.0, 12, 19);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (9, 15, 95.0, 15, 20);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (9, 13, 59.0, 13, 21);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (10, 4, 98.0, 4, 22);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (10, 6, 97.0, 6, 23);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (10, 7, 96.0, 7, 24);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 7, 95.0, 7, 25);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (12, 8, 69.0, 8, 26);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (12, 9, 85.0, 9, 27);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (10, 14, 100.0, 14, 28);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (6, 9, 100.0, 9, 29);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 1, 59.0, 1, 30);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 4, 90.0, 4, 31);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 5, 91.0, 5, 32);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 6, 58.0, 6, 33);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 8, 93.0, 8, 34);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 9, 57.0, 9, 35);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 10, 95.0, 10, 36);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 11, 96.0, 11, 37);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 12, 97.0, 12, 38);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 13, 98.0, 13, 39);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 14, 99.0, 14, 40);
insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 15, 89.0, 15, 41);
commit;

在思维举重前,先来一个热身运动吧:
--(一)查询选修课程名称为'JAVA程序设计'的学员学号和姓名 
--方法一:
--1.查询'JAVA程序设计'这门课程的课程号
--2.在成绩表中查询课程号为步骤1的课程号的成绩信息..
--3.在学生表中查询学号为步骤2结果的学生信息
select st.sno, st.sname
  from student st
 where st.sno in
       (select sno
          from score sc
         where sc.cno =
               (select co.cno from course co where co.cname = 'JAVA程序设计'));

--方法二:
--1.查询'JAVA程序设计'这门课程的课程号
--2.在成绩表和学生表关联结果中查询课程号等于步骤1的课程号的成绩信息.
--sql86
select st.sno, st.sname
  from student st, score sc
 where st.sno = sc.sno
   and sc.cno =
       (select co.cno from course co where co.cname = 'JAVA程序设计');
       
--sql92
select st.sno, st.sname
  from student st
  join score sc
    on st.sno = sc.sno
 where sc.cno =
       (select co.cno from course co where co.cname = 'JAVA程序设计');
       
--方法三:
--1.在成绩表和课程表关联结果中查询选修了'JAVA程序设计'这门课的学生的学号
--2.在学生表中查询步骤1中的学号的学生的详细信息.
--sql86
select st.sno, st.sname
  from student st
 where st.sno in (select sc.sno
                         from score sc, course co
                        where sc.cno = co.cno
                          and co.cname = 'JAVA程序设计');
 
--sql92 
 select st.sno, st.sname
   from student st
  where st.sno in (select sc.sno
                          from score sc
                          join course co
                            on sc.cno = co.cno  
                      where co.cname = 'JAVA程序设计');
                      
 --方法四:                     
 --在成绩表和课程表和学生表三表关联的结果中过滤得到选修了 'JAVA程序设计'的学生基本信息   
 --sql86
  select st.sno, st.sname
   from student st, score sc, course co
  where st.sno = sc.sno
    and co.cno = sc.cno
    and co.cname = 'JAVA程序设计';
             
 --sql92(1) 用where过滤
 select st.sno, st.sname
  from student st
  join score sc
    on st.sno = sc.sno
  join course co
    on co.cno = sc.cno
 where co.cname = 'JAVA程序设计';

--sql92(2) 在关联条件中过滤
 select st.sno, st.sname
   from student st
   join score sc
     on st.sno = sc.sno
   join course co
     on co.cno = sc.cno
    and co.cname = 'JAVA程序设计';
 
注: 1.对于sql86 和sql92的区别见这篇文章: http://blog.csdn.net/lk_blog/article/details/7580300
    2.如果您在看的过程中觉得不熟悉的地方很多,建议您先看此文: http://blog.csdn.net/lk_blog/article/details/7585501

进入正文:

--(一)查询不选修课程编号为'1'的学员姓名和所属单位 
--1.在成绩表中查询课程号为'1'的所有学生学号
--2.在学生表中查询学号不在步骤1中的学生的基本信息.
select st.sname, st.sdree
  from t_student st
 where st.sno not in (select sc.sno from t_score sc where sc.cno = '1');
 
 
 --(二)查询平均成绩大于85的所有学生的学号、姓名和平均成绩?
 select sc.sno, st.sname, avg(sc.grade)
   from t_score sc
   join t_student st
     on sc.sno = st.sno
  group by sc.sno, st.sname
 having avg(sc.grade) > 85; 
 
 --(三)查询课程名称为"JAVA程序设计",且分数低于60的学生姓名和分数
select st.sname, sc.grade
  from t_score sc
  join t_student st
    on sc.sno = st.sno
  join t_course co
    on sc.cno = co.cno
 where sc.grade < 60
   and co.cname = 'JAVA程序设计';
    
 select st.sname, sc.grade
   from t_score sc
   join t_student st
     on sc.sno = st.sno
   join t_course co
     on sc.cno = co.cno
    and sc.grade < 60
    and co.cname = 'JAVA程序设计' ;
     
select st.sname, sc.grade
  from t_score sc
  join t_student st
    on sc.sno = st.sno
 where sc.cno = (select cno from t_course where cname = 'JAVA程序设计')
   and sc.grade < 60
   

--(四)查询任何一门课程成绩全部都在70分以上的姓名、课程名称和分数?
--1.查询出成绩小于70分的学生的学号.
--2.将学生,成绩,课程三张表作关联.
--3.在关联表中过滤出不在步骤1查询结果中的学生信息.
select st.sname, co.cname, sc.grade
  from t_student st
  join t_score sc
    on st.sno = sc.sno
  join t_course co
    on sc.cno = co.cno
 where st.sno not in (select sc1.sno from t_score sc1 where sc1.grade < 70);
 
 
--(五)查询出选了课的学生的人数.
select count(distinct(sc.sno)) from t_score sc;


--(六)查询每门课程被选课的学生数
select sc.cno, count(distinct(sc.sno)) from t_score sc group by sc.cno;

             
--(七)查询选了全部课程的学员姓名和所属单位
--1.在课程表中查询出所有课程的数量
--2.在成绩表中查询出学生选课数等于步骤1中总选课数的学生的学号,注意要用distinct,having中可以使用count,where中不能使用count.
--3.在学生表中查出步骤2中学生的基本信息.
select st.sname, st.sdree
  from t_student st
 where st.sno in
       (select sc.sno
          from t_score sc
         group by sc.sno
        having count(distinct sc.cno) = (select count(distinct sc1.cno)
                                          from t_course sc1));
                                          
                                                                                       
--(八) 查询没有学全所有课的同学的学号、姓名
select st.sname, st.sdree
  from t_student st
 where st.sno in
       (select sc.sno
          from t_score sc
         group by sc.sno
        having count(distinct sc.cno) != (select count(*) from t_course));
 
        
--(九)查询选修课程超过5门的学员学号和所属单位 
--1.在成绩表中查询出选课程超过5门的学生学号.
--2.在学生表中查询步骤1中学号的学生的基本信息.
select st.sname, st.sdree
  from t_student st
 where st.sno in (select sc.sno
                         from t_score sc
                        group by sc.sno
                       having count(distinct sc.cno) > 5);
                                             
                                                                                
--(十)查询出没有选课的学生基本信息
--1.在成绩表中查询出所有选过课的学生的学号.
--2.在学生表中查询出步骤1中学生的基本信息.
select *
  from t_student st
 where st.sno not in (select sc.sno from t_score sc);

--下面的两个sql等价,在成绩表中数据量很大时使用下面的sql
select *
  from t_student st
 where st.sno not in (select distinct (sc.sno) from t_score sc);
 
select *
  from t_student st
 where st.sno not in (select sc.sno from t_score sc group by sc.sno);

                                                
--(十一) 列出有二门以上不及格课程的学生姓名及其平均成绩 
--方法一
--1.在成绩表中查询出2门不及格学生的学号,结果记作t1
--2.将学生表和t1和成绩表三表作关联得到关联表,在关联表中取学生基本信息和平均成绩.
--sql92   
select st.sno, st.sname, avg(sc.grade)
  from t_student st
  join (select sc.sno
          from t_score sc
         where sc.grade < 60
         group by sc.sno
        having count(distinct sc.cno) > 2) t1
    on st.sno = t1.sno
  join t_score sc
    on sc.sno = t1.sno
 group by st.sno, st.sname;
 
 --sql86
select st.sno, st.sname, avg(sc.grade)
  from t_student st,
       t_score sc,
       (select sc.sno
          from t_score sc
         where sc.grade < 60
         group by sc.sno
        having count(distinct sc.cno) > 2) t1
 where st.sno = t1.sno
   and sc.sno = t1.sno
 group by st.sno, st.sname;

--方法二:
--1.在成绩表中查询出2门不及格学生的学号
--2.将学生表和成绩表通过学号作关联并根据步骤1中的结果作过滤,在关联结果中取出学生基本信息和平均成绩                     
select st.sno, st.sname, avg(sc.grade)
  from t_student st
  join t_score sc
    on st.sno = sc.sno
 where st.sno in (select sc.sno
                    from t_score sc
                   where sc.grade < 60
                   group by sc.sno
                  having count(distinct sc.cno) > 2)
 group by st.sno, st.sname;

 
 --(十二) 查询平均成绩大于60分的同学的学号和平均成绩
--学生表和课程表关联,在having子句中过滤平均成绩大于60分.
select st.sno, avg(sc.grade)
  from t_student st, t_score sc
 where st.sno = sc.sno
 group by st.sno
having avg(sc.grade) > 60;

--1.学生表和课程表关联,将关联的结果记作t1
--2.在t1中过滤平均成绩大于60的学生学号.
select t1.sno, t1.avg_grade
  from (select st.sno, avg(sc.grade) avg_grade
          from t_student st, t_score sc
         where st.sno = sc.sno
         group by st.sno) t1
 where t1.avg_grade > 60;
 
 
--(十三)查询出只选修了一门课程的全部学生的学号和姓名
 --方法一:
 --1.将学生表和成绩表作关联,在分组函数中使用having子句过滤出只选了一门课程的学生基本信息.
 select sc.sno, st.sname
   from t_score sc
   join t_student st
     on sc.sno = st.sno
  group by sc.sno, st.sname
 having count(distinct sc.cno) = 1;
 
 --方法二:
 --1.在成绩表中查找学号,分组函数的过滤条件判断只选择了一门课程的学生.
 --2.在学生表中查找学号在步骤1中的值的学生的基本信息
select st.sno,st.sname
  from t_student st
 where st.sno in (select sc.sno
                    from t_score sc
                   group by sc.sno
                  having count(distinct sc.cno) = 1);
                  
 
                  
 --(十四)查询至少有一门课与学号为"1"的同学所学相同的同学的学号和姓名
select st.sno, st.sname
  from t_student st
  join t_score sc1
    on st.sno = sc1.sno
 where sc1.cno in (select sc.cno from t_score sc where sc.sno = '1')
 group by st.sno, st.sname;



--(十五)列出既学过"1"号课程,又学过"2"号课程的所有学生姓名
--1.将成绩表和课程表作关联,在关联条件中作过滤查询出既选过课程'1'又选过课程'2'的学生的学号,注意看 co.cno in ('1', '2')和having count(distinct sc.cno) = 2 的位置.
--2.在学生表中根据步骤1的结果作过滤查询出学生的基本信息.
--方法一:
--sql86
select st.sno, st.sname
  from t_student st,
       (select sc.sno
          from t_score sc, t_course co
         where sc.cno = co.cno
           and co.cno in ('1', '2')
         group by sc.sno
        having count(distinct sc.cno) = 2) t1
 where st.sno = t1.sno;
 
 --sql92
 select st.sno, st.sname
  from t_student st join 
       (select sc.sno
          from t_score sc join t_course co
         on sc.cno = co.cno
           and co.cno in ('1', '2')
         group by sc.sno
        having count(distinct sc.cno) = 2) t1
 on st.sno = t1.sno;
 
 --方法二:
 --sql86
 select st.sno, st.sname
   from t_student st
  where st.sno in (select sc.sno
                     from t_score sc, t_course co
                    where sc.cno = co.cno
                      and co.cno in ('1', '2')
                    group by sc.sno
                   having count(distinct sc.cno) = 2);
 
--sql92 
  select st.sno, st.sname
    from t_student st
   where st.sno in (select sc.sno
                      from t_score sc
                      join t_course co
                        on sc.cno = co.cno
                       and co.cno in ('1', '2')
                     group by sc.sno
                    having count(distinct sc.cno) = 2);
 
 
 
 --(十六)查询至少学过学号为"1"的同学所有门课的同学学号和姓名
 --1.查询出'1'号同学学习的全部课程.
 --2.查询出'1'号同学学习全部课程的数量.
 --3.将课程表和成绩表做关联,在关联表中查询出学生的学号,关联条件中加入过滤条件[课程号在步骤1查询结果范围内],过滤条件中加入数量等级步骤2中得到的数量.
 --4.在学生表中查询步骤3中的学号的学生的基本信息.
select st.sno, st.sname
  from t_student st
 where st.sno in
       (select sc.sno
          from t_score sc
          join t_course co
            on sc.cno = co.cno
           and co.cno in (select sc.cno from t_score sc where sc.sno = '1')
         group by sc.sno
        having count(distinct sc.cno) = (select count(distinct sc.cno)
                                          from t_score sc
                                         where sc.sno = '1'))
                                         
  
                                         
 --(十七)查询和"6"号同学学习的课程完全相同的同学的学号和姓名
 --分析:要查询与6号同学完全相同的课程的学生信息,等价于学过6号同学的学过的所有课程并且选课数量与6同学选课数量相等.
 --方法一: 
 --1.查询出'1'号同学学习的全部课程.
 --2.查询出'1'号同学学习全部课程的数量.
 --3.将课程表和成绩表做关联,在关联表中查询出学生的学号和选课数量,记作 t2,关联条件中加入过滤条件[课程号在步骤1查询结果范围内],过滤条件中加入数量等级步骤2中得到的数量.
 --4.在成绩表中查询出学号和每个学生选课数量.得到结果记作: t1
 --5.将步骤3中的t2和步骤4中的t1通过学生学号关联,添加过滤条件,t1中的选课数量等于t2中的选课数量.
 --6.在学生表中查询不步骤5的学生学号的基本信息.
 select st.sno, st.sname
   from t_student st
  where st.sno in
        (select t1.sno
           from (select sc_a.sno, count(distinct sc_a.cno) num_outer
                   from t_score sc_a
                  group by sc_a.sno) t1
           join (select sc.sno, count(distinct sc.cno) num_inner
                  from t_score sc
                  join t_course co
                    on sc.cno = co.cno
                   and co.cno in
                       (select sc.cno from t_score sc where sc.sno = '6')
                 group by sc.sno
                having count(distinct sc.cno) = (select count(distinct sc.cno)
                                                  from t_score sc
                                                 where sc.sno = '6')) t2
             on t1.sno = t2.sno
          where t1.num_outer = t2.num_inner);
          
  
          
 --(十八)列出"1"号课成绩比"2"号课成绩高的所有学生的学号及其"1"号课和"2"号课的成绩
 --1.将学生表和课程表作两次关联,一次关联用于取该学生课程'1'的成绩,另一次关联用于取该学生课程'2'的成绩.
 --sql86
select st.sno, st.sname, sc_a.grade, sc_b.grade
  from t_student st, t_score sc_a, t_score sc_b
 where sc_a.cno = '1'
   and sc_b.cno = '2'
   and st.sno = sc_a.sno
   and st.sno = sc_b.sno
   and sc_a.grade > sc_b.grade
   
 --sql92
select st.sno, st.sname, sc_a.grade, sc_b.grade
  from t_student st
  join t_score sc_a
    on st.sno = sc_a.sno
  join t_score sc_b
    on st.sno = sc_b.sno
 where sc_a.cno = '1'
   and sc_b.cno = '2'
   and sc_a.grade > sc_b.grade
   


--(十九)查询所有同学的学号、姓名、选课数、总成绩
select st.sno, st.sname, count(sc.cno), sum(sc.grade)
  from t_student st, t_score sc
 where st.sno = sc.sno
 group by st.sno, st.sname;



--(二十)查询课程成绩小于60分的同学的学号,姓名,课程名,成绩
--下面两条sql虽然结果相同,但意义不同,注意理解一下哦.
--1.将学生表,课程表,成绩表作关联
--2.对关联后的结果作过滤,过滤出成绩小于60的学生基本信息.
select st.sno, st.sname, co.cname, sc.grade
  from t_score sc
  join t_student st
    on sc.sno = st.sno
  join t_course co
    on sc.cno = co.cno
 where sc.grade < 60

--1.将学生表,课程表,成绩表作关联,在关联条件中过滤成绩小于60.
 select st.sno, st.sname, co.cname, sc.grade
  from t_score sc
  join t_student st
    on sc.sno = st.sno
  join t_course co
    on sc.cno = co.cno
and sc.grade <60



--(二十一)按平均成绩从到低显示所有学生的"JAVA程序设计"、"J2EE从入门到精通"、"EJB及设计模式"三门的课程成绩,
--并按如下形式显示: 学生ID,姓名,JAVA程序设计,J2EE从入门到精通,EJB及设计模式,有效课程数,有效课程平均分
--1.将成绩表和课程表关联得到结果记作: t1, 关联时的条件选择只统计以上三门课程.
--2.按题目中的要求组织统计结果.
select st.sno,
       st.sname,
       sum(decode(t1.cname, 'JAVA程序设计', t1.grade)) JAVA程序设计,
       sum(decode(t1.cname, 'J2EE从入门到精通', t1.grade)) J2EE从入门到精通,
       sum(decode(t1.cname, 'EJB及设计模式', t1.grade)) EJB及设计模式,
       count(distinct t1.grade) 有效课程数,
       avg(t1.grade) 有效课程平均分
  from t_student st
  join (select *
          from t_score sc
          join t_course co
            on sc.cno = co.cno
           and co.cname in
               ('JAVA程序设计', 'J2EE从入门到精通', 'EJB及设计模式')) t1
    on st.sno = t1.sno
 group by st.sno, st.sname
   
 --将decode可以换成case when 第一种形式
 select st.sno,
        st.sname,
        sum(case t1.cname
              when 'JAVA程序设计' then
               t1.grade
            end) JAVA程序设计,
         sum(case t1.cname
              when 'J2EE从入门到精通' then
               t1.grade
            end) J2EE从入门到精通,
             sum(case t1.cname
              when 'EJB及设计模式' then
               t1.grade
            end) EJB及设计模式,
        count(distinct t1.grade) 有效课程数,
        avg(t1.grade) 有效课程平均分
   from t_student st
   join (select *
           from t_score sc
           join t_course co
             on sc.cno = co.cno
            and co.cname in
                ('JAVA程序设计', 'J2EE从入门到精通', 'EJB及设计模式')) t1
     on st.sno = t1.sno
  group by st.sno, st.sname
  
  
 --将decode可以换成case when 第二种形式
  select st.sno,
         st.sname,
         sum(case
               when t1.cname = 'JAVA程序设计' then
                t1.grade
             end) JAVA程序设计,
         sum(case
               when t1.cname = 'J2EE从入门到精通' then
                t1.grade
             end) J2EE从入门到精通,
         sum(case
               when t1.cname = 'EJB及设计模式' then
                t1.grade
             end) EJB及设计模式,
         count(distinct t1.grade) 有效课程数,
         avg(t1.grade) 有效课程平均分
    from t_student st
    join (select *
            from t_score sc
            join t_course co
              on sc.cno = co.cno
             and co.cname in
                 ('JAVA程序设计', 'J2EE从入门到精通', 'EJB及设计模式')) t1
      on st.sno = t1.sno
   group by st.sno, st.sname
 
 
--(二十二)查询各科成绩最高和最低的分:以如下形式显示:课程ID,课程名,最高分,最低分
select sc.cno, co.cname, max(grade), min(grade)
  from t_score sc
  join t_course co
    on sc.cno = co.cno
 group by sc.cno, co.cname


--(二十三)按各科平均成绩从低到高和及格率的百分数从高到低顺序 
--1.在成绩表中查出课程号,平均成绩,课程人数,记作 : t1
--2.在成绩表中查出课程号,及格的课程人数,记作 : t2
--3.将步骤1中的成绩和步骤2中的课程2关联,查出所要的结果并排序.
select t1.cno, t1.avg_num 平均成绩, (count_num1 / count_num) * 100 及格率
  from (select sc.cno, avg(grade) avg_num, count(distinct sc.sno) count_num
          from t_score sc
         group by sc.cno) t1
  join (select sc1.cno, count(distinct sc1.sno) count_num1
          from t_score sc1
         where sc1.grade > 60
         group by sc1.cno) t2
    on t1.cno = t2.cno
 order by t1.avg_num asc, 及格率 desc
 
 
--(二十四)统计各科成绩,各分数段人数:课程ID,课程名称,[100-90]优,[90-80]良,[80-70]中,[70-60]一般,[<60]不及格
--1.在成绩表中根据成绩值分段
--2.将步骤1中的结果与课程表关联.
select sc.cno,co.cname,
       sum(case
             when sc.grade > 90 then
              1
           end) 优,
       sum(case
             when sc.grade > 80 and sc.grade < 90 then
              1
           end) 良,
       sum(case
             when sc.grade > 70 and sc.grade < 80 then
              1
           end) 中,
       sum(case
             when sc.grade > 60 and sc.grade < 70 then
              1
           end) 一般,
       sum(case
             when sc.grade < 60 then
              1
           end) 不及格
  from t_score sc join t_course co on sc.cno = co.cno
 group by sc.cno,co.cname

--(二十五)查询学生平均成绩及其名次
select st.sno, st.sname, avg(sc.grade) avg_num
  from t_score sc
  join t_student st
    on sc.sno = st.sno
 group by st.sno, st.sname
 order by avg_num desc



--(二十六)查询课程号分别为1,2,3的课程,成绩前三名的学生基本信息:(不考虑成绩并列情况)
--方法一:
--1.分别查出1,2,3各自的前3名的学生的学号,并用union all将结果集关联.
--2.在学生表中查询步骤1中查到的id的学生的基本信息.
select *
  from t_student
 where sno in (select t1.sno
                 from (select sc1.*
                         from t_score sc1
                        where sc1.cno = 1
                        order by sc1.grade desc) t1
                where rownum < 4
               union all
               select t1.sno
                 from (select sc1.*
                         from t_score sc1
                        where sc1.cno = 2
                        order by sc1.grade desc) t1
                where rownum < 4
               union all
               select t1.sno
                 from (select sc1.*
                         from t_score sc1
                        where sc1.cno = 3
                        order by sc1.grade desc) t1
                where rownum < 4)

--方法二:
 --rank() over(Partition .. order by ...) 是按照某个字段的值进行分组并编号
select t1.cno, t1.sno, t1.grade, r
  from (select sc.sno,
               sc.cno,
               sc.grade,
               rank() over(partition by sc.cno order by grade desc) r
          from t_score sc) t1
 where r < 4
   and t1.cno in (1, 2, 3)
 order by t1.cno, t1.sno, r;


 --(二十七)查询各科成绩前三名的记录(不考虑成绩并列情况)
 --rank() over(Partition .. order by ...) 是按照某个字段的值进行分组并编号
select t1.cno, t1.sno, t1.grade, r
  from (select sc.sno,
               sc.cno,
               sc.grade,
               rank() over(partition by sc.cno order by grade desc) r
          from t_score sc) t1
 where r < 4
 order by t1.cno, t1.sno, r;
  


 

 

相关推荐
<div style="color:rgba(0,0,0,.75);"> <span style="color:#4d4d4d;"> </span> <div style="color:rgba(0,0,0,.75);"> <span style="color:#4d4d4d;"> </span> <div style="color:rgba(0,0,0,.75);"> <div style="color:rgba(0,0,0,.75);"> <span style="color:#4d4d4d;">当前课程中商城项目的实战源码是我发布在 GitHub 上的开源项目 newbee-mall (新蜂商城),目前已有 6300 多个 star,</span><span style="color:#4d4d4d;">本课程是一个 Spring Boot 技术栈的实战类课程,课程共分为 3 大部分,前面两个部分为基础环境准备和相关概念介绍,第三个部分是 Spring Boot 商城项目功能的讲解,让大家实际操作并实践上手一个大型的线上商城项目,并学习到一定的开发经验以及其中的开发技巧。<br /> 商城项目所涉及的功能结构图整理如下:<br /> </span> </div> <div style="color:rgba(0,0,0,.75);">   </div> <div style="color:rgba(0,0,0,.75);"> <p style="color:#4d4d4d;"> <img alt="modules" src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9uZXdiZWUtbWFsbC5vc3MtY24tYmVpamluZy5hbGl5dW5jcy5jb20vcG9zdGVyL3N0b3JlL25ld2JlZS1tYWxsLXMucG5n?x-oss-process=image/format,png" /> </p> </div> <p style="color:rgba(0,0,0,.75);"> <strong><span style="color:#e53333;">课程特色</span></strong> </p> <p style="color:rgba(0,0,0,.75);">   </p> <div style="color:rgba(0,0,0,.75);">   </div> <div style="color:rgba(0,0,0,.75);"> <ul> <li> 对新手开发者十分友好,无需复杂的操作步骤,仅需 2 秒就可以启动这个完整的商城项目 </li> <li> 最终的实战项目是一个企业级别的 Spring Boot 大型项目,对于各个阶段的 Java 开发者都是极佳的选择 </li> <li> 实践项目页面美观且实用,交互效果完美 </li> <li> 教程详细开发教程详细完整、文档资源齐全 </li> <li> 代码+讲解+演示网站全方位保证,向 Hello World 教程说拜拜 </li> <li> 技术栈新颖且知识点丰富,学习后可以提升大家对于知识的理解和掌握,可以进一步提升你的市场竞争力 </li> </ul> </div> <p style="color:rgba(0,0,0,.75);">   </p> <p style="color:rgba(0,0,0,.75);"> <span style="color:#e53333;">课程预览</span> </p> <p style="color:rgba(0,0,0,.75);">   </p> <div style="color:rgba(0,0,0,.75);">   </div> <div style="color:rgba(0,0,0,.75);"> <p style="color:#4d4d4d;"> 以下为商城项目的页面和功能展示,分别为: </p> </div> <div style="color:rgba(0,0,0,.75);"> <ul> <li> 商城首页 1<br /> <img alt="" src="https://img-bss.csdnimg.cn/202103050347585499.gif" /> </li> <li> 商城首页 2<br /> <img alt="" src="https://img-bss.csdn.net/202005181054413605.png" /> </li> <li>   </li> <li> 购物车<br /> <img alt="cart" src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9uZXdiZWUtbWFsbC5vc3MtY24tYmVpamluZy5hbGl5dW5jcy5jb20vcG9zdGVyL3Byb2R1Y3QvY2FydC5wbmc?x-oss-process=image/format,png" /> </li> <li> 订单结算<br /> <img alt="settle" src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9uZXdiZWUtbWFsbC5vc3MtY24tYmVpamluZy5hbGl5dW5jcy5jb20vcG9zdGVyL3Byb2R1Y3Qvc2V0dGxlLnBuZw?x-oss-process=image/format,png" /> </li> <li> 订单列表<br /> <img alt="orders" src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9uZXdiZWUtbWFsbC5vc3MtY24tYmVpamluZy5hbGl5dW5jcy5jb20vcG9zdGVyL3Byb2R1Y3Qvb3JkZXJzLnBuZw?x-oss-process=image/format,png" /> </li> <li> 支付页面<br /> <img alt="" src="https://img-bss.csdn.net/201909280301493716.jpg" /> </li> <li> 后台管理系统登录页<br /> <img alt="login" src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9uZXdiZWUtbWFsbC5vc3MtY24tYmVpamluZy5hbGl5dW5jcy5jb20vcG9zdGVyL3Byb2R1Y3QvbWFuYWdlLWxvZ2luLnBuZw?x-oss-process=image/format,png" /> </li> <li> 商品管理<br /> <img alt="goods" src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9uZXdiZWUtbWFsbC5vc3MtY24tYmVpamluZy5hbGl5dW5jcy5jb20vcG9zdGVyL3Byb2R1Y3QvbWFuYWdlLWdvb2RzLnBuZw?x-oss-process=image/format,png" /> </li> <li> 商品编辑<br /> <img alt="" src="https://img-bss.csdnimg.cn/202103050348242799.png" /> </li> </ul> </div> </div> </div> </div>
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页