花了几个小时研究了坤哥博客里的sql举重思维训练,原生sql语句是一个高级程序员的必备基础,这里在坤哥的基础上,做些简单的思路总结。
建表和初始化sql(本例子使用oralce数据库):
- <span style="font-size:18px;">--创建表
- 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;
- </span>
思维举重前的热身运动:
- <strong><span style="font-size:18px;">--(一)查询选修课程名称为'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.如果您在看的过程中觉得不熟悉的地方很多,建议您先看此文: </span><a target=_blank href="http://blog.csdn.net/lk_blog/article/details/7585501"><span style="font-size:18px;">http://blog.csdn.net/lk_blog/article/details/7585501</span></a></strong>
进入正文:
- <span style="font-size:18px;"><strong>--(一)查询不选修课程编号为'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;
- </strong></span>
总结:
1、在开发Oracle9i时, 数据库还时间了ANSL SQL/92标准的链接语法, 在书中建议在使用Oracle 9i及更高版本时,应该使用SQL/92标准的语法;在使用Oracle 8i 及更低版本时,应该使用SQL/86标准的语法。
2、多表查询时,可以先创建相互连接的表,之后再添加过滤条件;也可以使用where逐条限制;中间关联表可以和左边的表先建立关联,也可以和右边的表先建立连接,也可以将相关的左右表一次性建立关联,不同的关联策略需要配合不同的筛选条件。
3、join on and 和join on where 可以得到相同的结果,但意义不同。
4、一些使用join的地方可以使用in。
5、如果遇到“至少”这样的需求往往会用到in。
6、当查询出的结果有重复的时候使用group by,如果还需要进一步筛选,配合使用having。
7、同一张表和不同表关联一样,重视自身关联。
8、Oracle函数运用:rank() over(Partition .. order by ...) 是按照某个字段的值进行分组并编号 可以替代原生的case 语句。