Oracle优化之sql基本功

 花了几个小时研究了坤哥博客里的sql举重思维训练,原生sql语句是一个高级程序员的必备基础,这里在坤哥的基础上,做些简单的思路总结。

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

[sql]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-size:18px;">--创建表  
  2. create table T_STUDENT(sno NUMBER not null,  sname VARCHAR2(30),  sdree VARCHAR2(50),  sage  NUMBER,  ssex  CHAR(2));  
  3. alter table T_STUDENT add primary key (SNO);  
  4. create table T_SCORE(sno   NUMBER,  cno   NUMBER,  grade NUMBER(4,1), tno NUMBER,  id NUMBER not null);  
  5. alter table T_SCORE add primary key (ID);  
  6. create table T_COURSE(cno NUMBER not null,  cname VARCHAR2(30));  
  7. alter table T_COURSE add primary key (CNO);  
  8.   
  9. --初始化学生表  
  10. insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (1, '李坤''天融信', 26, '男');  
  11. insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (2, '曹贵生''中银', 26, '男');  
  12. insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (3, '柳波''买卖宝', 27, '男');  
  13. insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (4, '纪争光''IBM', 23, '男');  
  14. insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (5, '李学宇''微软', 25, '女');  
  15. insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (6, '李雪琪''文思创新', 25, '女');  
  16. insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (7, '陈绪''中海油', 26, '男');  
  17. insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (8, '韩正阳''中海油', 24, '男');  
  18. insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (9, '陈伟东''中核', 24, '男');  
  19. insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (10, '刘兵''优酷', 24, '男');  
  20. insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (11, '丁成云''联想', 25, '女');  
  21. insert into T_STUDENT (SNO, SNAME, SDREE, SAGE, SSEX) values (12, '王鹏''中兴', 25, '男');  
  22. commit;  
  23.   
  24. --初始化课程表  
  25. insert into T_COURSE (CNO, CNAME) values (1, 'JAVA程序设计');  
  26. insert into T_COURSE (CNO, CNAME) values (2, 'ORACLE开发');  
  27. insert into T_COURSE (CNO, CNAME) values (3, 'C++程序设计');  
  28. insert into T_COURSE (CNO, CNAME) values (4, 'C#程序设计');  
  29. insert into T_COURSE (CNO, CNAME) values (5, 'Windows实战');  
  30. insert into T_COURSE (CNO, CNAME) values (6, 'Center OS教程');  
  31. insert into T_COURSE (CNO, CNAME) values (7, 'Jsp/Servlet开发');  
  32. insert into T_COURSE (CNO, CNAME) values (8, 'J2EE从入门到精通');  
  33. insert into T_COURSE (CNO, CNAME) values (9, 'EJB及设计模式');  
  34. insert into T_COURSE (CNO, CNAME) values (10, 'Javascript/jQuery实战');  
  35. insert into T_COURSE (CNO, CNAME) values (11, 'Flash设计');  
  36. insert into T_COURSE (CNO, CNAME) values (12, 'HTML/CSS/JAVASCRIPT实战');  
  37. insert into T_COURSE (CNO, CNAME) values (13, '精通ASP.NET');  
  38. insert into T_COURSE (CNO, CNAME) values (14, 'JBoss入门');  
  39. insert into T_COURSE (CNO, CNAME) values (15, 'Spring开发');  
  40. commit;  
  41.   
  42. --初始化成绩表  
  43. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (1, 2, 90.0, 2, 1);  
  44. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (1, 3, 80.0, 3, 2);  
  45. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (1, 4, 90.0, 4, 3);  
  46. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 2, 70.0, 2, 4);  
  47. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (2, 11, 66.0, 11, 5);  
  48. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (2, 15, 77.0, 15, 6);  
  49. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (2, 8, 87.0, 8, 7);  
  50. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (2, 6, 96.0, 6, 8);  
  51. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (3, 2, 89.0, 2, 9);  
  52. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (3, 1, 91.0, 1, 10);  
  53. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (4, 2, 83.0, 2, 11);  
  54. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (5, 4, 73.0, 4, 12);  
  55. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (5, 1, 60.0, 1, 13);  
  56. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (5, 8, 82.0, 8, 14);  
  57. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (6, 8, 90.5, 10, 15);  
  58. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (8, 2, 58.0, 2, 16);  
  59. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 3, 80.0, 3, 17);  
  60. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (9, 11, 65.0, 11, 18);  
  61. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (9, 12, 67.0, 12, 19);  
  62. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (9, 15, 95.0, 15, 20);  
  63. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (9, 13, 59.0, 13, 21);  
  64. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (10, 4, 98.0, 4, 22);  
  65. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (10, 6, 97.0, 6, 23);  
  66. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (10, 7, 96.0, 7, 24);  
  67. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 7, 95.0, 7, 25);  
  68. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (12, 8, 69.0, 8, 26);  
  69. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (12, 9, 85.0, 9, 27);  
  70. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (10, 14, 100.0, 14, 28);  
  71. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (6, 9, 100.0, 9, 29);  
  72. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 1, 59.0, 1, 30);  
  73. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 4, 90.0, 4, 31);  
  74. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 5, 91.0, 5, 32);  
  75. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 6, 58.0, 6, 33);  
  76. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 8, 93.0, 8, 34);  
  77. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 9, 57.0, 9, 35);  
  78. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 10, 95.0, 10, 36);  
  79. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 11, 96.0, 11, 37);  
  80. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 12, 97.0, 12, 38);  
  81. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 13, 98.0, 13, 39);  
  82. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 14, 99.0, 14, 40);  
  83. insert into T_SCORE (SNO, CNO, GRADE, TNO, ID) values (11, 15, 89.0, 15, 41);  
  84. commit;  
  85.   
  86. </span>  

思维举重前的热身运动:

[sql]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <strong><span style="font-size:18px;">--(一)查询选修课程名称为'JAVA程序设计'的学员学号和姓名   
  2. --方法一:  
  3. --1.查询'JAVA程序设计'这门课程的课程号  
  4. --2.在成绩表中查询课程号为步骤1的课程号的成绩信息..  
  5. --3.在学生表中查询学号为步骤2结果的学生信息  
  6. select st.sno, st.sname  
  7.   from student st  
  8.  where st.sno in  
  9.        (select sno  
  10.           from score sc  
  11.          where sc.cno =  
  12.                (select co.cno from course co where co.cname = 'JAVA程序设计'));  
  13.   
  14. --方法二:  
  15. --1.查询'JAVA程序设计'这门课程的课程号  
  16. --2.在成绩表和学生表关联结果中查询课程号等于步骤1的课程号的成绩信息.  
  17. --sql86  
  18. select st.sno, st.sname  
  19.   from student st, score sc  
  20.  where st.sno = sc.sno  
  21.    and sc.cno =  
  22.        (select co.cno from course co where co.cname = 'JAVA程序设计');  
  23.          
  24. --sql92  
  25. select st.sno, st.sname  
  26.   from student st  
  27.   join score sc  
  28.     on st.sno = sc.sno  
  29.  where sc.cno =  
  30.        (select co.cno from course co where co.cname = 'JAVA程序设计');  
  31.          
  32. --方法三:  
  33. --1.在成绩表和课程表关联结果中查询选修了'JAVA程序设计'这门课的学生的学号  
  34. --2.在学生表中查询步骤1中的学号的学生的详细信息.  
  35. --sql86  
  36. select st.sno, st.sname  
  37.   from student st  
  38.  where st.sno in (select sc.sno  
  39.                          from score sc, course co  
  40.                         where sc.cno = co.cno  
  41.                           and co.cname = 'JAVA程序设计');  
  42.    
  43. --sql92   
  44.  select st.sno, st.sname  
  45.    from student st  
  46.   where st.sno in (select sc.sno  
  47.                           from score sc  
  48.                           join course co  
  49.                             on sc.cno = co.cno    
  50.                       where co.cname = 'JAVA程序设计');  
  51.                         
  52.  --方法四:                       
  53.  --在成绩表和课程表和学生表三表关联的结果中过滤得到选修了 'JAVA程序设计'的学生基本信息     
  54.  --sql86  
  55.   select st.sno, st.sname  
  56.    from student st, score sc, course co  
  57.   where st.sno = sc.sno  
  58.     and co.cno = sc.cno  
  59.     and co.cname = 'JAVA程序设计';  
  60.                
  61.  --sql92(1) 用where过滤  
  62.  select st.sno, st.sname  
  63.   from student st  
  64.   join score sc  
  65.     on st.sno = sc.sno  
  66.   join course co  
  67.     on co.cno = sc.cno  
  68.  where co.cname = 'JAVA程序设计';  
  69.   
  70. --sql92(2) 在关联条件中过滤  
  71.  select st.sno, st.sname  
  72.    from student st  
  73.    join score sc  
  74.      on st.sno = sc.sno  
  75.    join course co  
  76.      on co.cno = sc.cno  
  77.     and co.cname = 'JAVA程序设计';  
  78.    
  79. 注: 1.对于sql86 和sql92的区别见这篇文章: http://blog.csdn.net/lk_blog/article/details/7580300  
  80.     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>  


进入正文:

[sql]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-size:18px;"><strong>--(一)查询不选修课程编号为'1'的学员姓名和所属单位   
  2. --1.在成绩表中查询课程号为'1'的所有学生学号  
  3. --2.在学生表中查询学号不在步骤1中的学生的基本信息.  
  4. select st.sname, st.sdree  
  5.   from t_student st  
  6.  where st.sno not in (select sc.sno from t_score sc where sc.cno = '1');  
  7.    
  8.    
  9.  --(二)查询平均成绩大于85的所有学生的学号、姓名和平均成绩?  
  10.  select sc.sno, st.sname, avg(sc.grade)  
  11.    from t_score sc  
  12.    join t_student st  
  13.      on sc.sno = st.sno  
  14.   group by sc.sno, st.sname  
  15.  having avg(sc.grade) > 85;   
  16.    
  17.  --(三)查询课程名称为"JAVA程序设计",且分数低于60的学生姓名和分数  
  18. select st.sname, sc.grade  
  19.   from t_score sc  
  20.   join t_student st  
  21.     on sc.sno = st.sno  
  22.   join t_course co  
  23.     on sc.cno = co.cno  
  24.  where sc.grade < 60  
  25.    and co.cname = 'JAVA程序设计';  
  26.       
  27.  select st.sname, sc.grade  
  28.    from t_score sc  
  29.    join t_student st  
  30.      on sc.sno = st.sno  
  31.    join t_course co  
  32.      on sc.cno = co.cno  
  33.     and sc.grade < 60  
  34.     and co.cname = 'JAVA程序设计' ;  
  35.        
  36. select st.sname, sc.grade  
  37.   from t_score sc  
  38.   join t_student st  
  39.     on sc.sno = st.sno  
  40.  where sc.cno = (select cno from t_course where cname = 'JAVA程序设计')  
  41.    and sc.grade < 60  
  42.      
  43.   
  44. --(四)查询任何一门课程成绩全部都在70分以上的姓名、课程名称和分数?  
  45. --1.查询出成绩小于70分的学生的学号.  
  46. --2.将学生,成绩,课程三张表作关联.  
  47. --3.在关联表中过滤出不在步骤1查询结果中的学生信息.  
  48. select st.sname, co.cname, sc.grade  
  49.   from t_student st  
  50.   join t_score sc  
  51.     on st.sno = sc.sno  
  52.   join t_course co  
  53.     on sc.cno = co.cno  
  54.  where st.sno not in (select sc1.sno from t_score sc1 where sc1.grade < 70);  
  55.    
  56.    
  57. --(五)查询出选了课的学生的人数.  
  58. select count(distinct(sc.sno)) from t_score sc;  
  59.   
  60.   
  61. --(六)查询每门课程被选课的学生数  
  62. select sc.cno, count(distinct(sc.sno)) from t_score sc group by sc.cno;  
  63.   
  64.                
  65. --(七)查询选了全部课程的学员姓名和所属单位  
  66. --1.在课程表中查询出所有课程的数量  
  67. --2.在成绩表中查询出学生选课数等于步骤1中总选课数的学生的学号,注意要用distinct,having中可以使用count,where中不能使用count.  
  68. --3.在学生表中查出步骤2中学生的基本信息.  
  69. select st.sname, st.sdree  
  70.   from t_student st  
  71.  where st.sno in  
  72.        (select sc.sno  
  73.           from t_score sc  
  74.          group by sc.sno  
  75.         having count(distinct sc.cno) = (select count(distinct sc1.cno)  
  76.                                           from t_course sc1));  
  77.                                             
  78.                                                                                          
  79. --(八) 查询没有学全所有课的同学的学号、姓名  
  80. select st.sname, st.sdree  
  81.   from t_student st  
  82.  where st.sno in  
  83.        (select sc.sno  
  84.           from t_score sc  
  85.          group by sc.sno  
  86.         having count(distinct sc.cno) != (select count(*) from t_course));  
  87.    
  88.           
  89. --(九)查询选修课程超过5门的学员学号和所属单位   
  90. --1.在成绩表中查询出选课程超过5门的学生学号.  
  91. --2.在学生表中查询步骤1中学号的学生的基本信息.  
  92. select st.sname, st.sdree  
  93.   from t_student st  
  94.  where st.sno in (select sc.sno  
  95.                          from t_score sc  
  96.                         group by sc.sno  
  97.                        having count(distinct sc.cno) > 5);  
  98.                                                
  99.                                                                                   
  100. --(十)查询出没有选课的学生基本信息  
  101. --1.在成绩表中查询出所有选过课的学生的学号.  
  102. --2.在学生表中查询出步骤1中学生的基本信息.  
  103. select *  
  104.   from t_student st  
  105.  where st.sno not in (select sc.sno from t_score sc);  
  106.   
  107. --下面的两个sql等价,在成绩表中数据量很大时使用下面的sql  
  108. select *  
  109.   from t_student st  
  110.  where st.sno not in (select distinct (sc.sno) from t_score sc);  
  111.    
  112. select *  
  113.   from t_student st  
  114.  where st.sno not in (select sc.sno from t_score sc group by sc.sno);  
  115.   
  116.                                                   
  117. --(十一) 列出有二门以上不及格课程的学生姓名及其平均成绩   
  118. --方法一  
  119. --1.在成绩表中查询出2门不及格学生的学号,结果记作t1  
  120. --2.将学生表和t1和成绩表三表作关联得到关联表,在关联表中取学生基本信息和平均成绩.  
  121. --sql92     
  122. select st.sno, st.sname, avg(sc.grade)  
  123.   from t_student st  
  124.   join (select sc.sno  
  125.           from t_score sc  
  126.          where sc.grade < 60  
  127.          group by sc.sno  
  128.         having count(distinct sc.cno) > 2) t1  
  129.     on st.sno = t1.sno  
  130.   join t_score sc  
  131.     on sc.sno = t1.sno  
  132.  group by st.sno, st.sname;  
  133.    
  134.  --sql86  
  135. select st.sno, st.sname, avg(sc.grade)  
  136.   from t_student st,  
  137.        t_score sc,  
  138.        (select sc.sno  
  139.           from t_score sc  
  140.          where sc.grade < 60  
  141.          group by sc.sno  
  142.         having count(distinct sc.cno) > 2) t1  
  143.  where st.sno = t1.sno  
  144.    and sc.sno = t1.sno  
  145.  group by st.sno, st.sname;  
  146.   
  147. --方法二:  
  148. --1.在成绩表中查询出2门不及格学生的学号  
  149. --2.将学生表和成绩表通过学号作关联并根据步骤1中的结果作过滤,在关联结果中取出学生基本信息和平均成绩                       
  150. select st.sno, st.sname, avg(sc.grade)  
  151.   from t_student st  
  152.   join t_score sc  
  153.     on st.sno = sc.sno  
  154.  where st.sno in (select sc.sno  
  155.                     from t_score sc  
  156.                    where sc.grade < 60  
  157.                    group by sc.sno  
  158.                   having count(distinct sc.cno) > 2)  
  159.  group by st.sno, st.sname;  
  160.   
  161.    
  162.  --(十二) 查询平均成绩大于60分的同学的学号和平均成绩  
  163. --学生表和课程表关联,在having子句中过滤平均成绩大于60分.  
  164. select st.sno, avg(sc.grade)  
  165.   from t_student st, t_score sc  
  166.  where st.sno = sc.sno  
  167.  group by st.sno  
  168. having avg(sc.grade) > 60;  
  169.   
  170. --1.学生表和课程表关联,将关联的结果记作t1  
  171. --2.在t1中过滤平均成绩大于60的学生学号.  
  172. select t1.sno, t1.avg_grade  
  173.   from (select st.sno, avg(sc.grade) avg_grade  
  174.           from t_student st, t_score sc  
  175.          where st.sno = sc.sno  
  176.          group by st.sno) t1  
  177.  where t1.avg_grade > 60;  
  178.    
  179.    
  180. --(十三)查询出只选修了一门课程的全部学生的学号和姓名  
  181.  --方法一:  
  182.  --1.将学生表和成绩表作关联,在分组函数中使用having子句过滤出只选了一门课程的学生基本信息.  
  183.  select sc.sno, st.sname  
  184.    from t_score sc  
  185.    join t_student st  
  186.      on sc.sno = st.sno  
  187.   group by sc.sno, st.sname  
  188.  having count(distinct sc.cno) = 1;  
  189.    
  190.  --方法二:  
  191.  --1.在成绩表中查找学号,分组函数的过滤条件判断只选择了一门课程的学生.  
  192.  --2.在学生表中查找学号在步骤1中的值的学生的基本信息  
  193. select st.sno,st.sname  
  194.   from t_student st  
  195.  where st.sno in (select sc.sno  
  196.                     from t_score sc  
  197.                    group by sc.sno  
  198.                   having count(distinct sc.cno) = 1);  
  199.                     
  200.    
  201.                     
  202.  --(十四)查询至少有一门课与学号为"1"的同学所学相同的同学的学号和姓名  
  203. select st.sno, st.sname  
  204.   from t_student st  
  205.   join t_score sc1  
  206.     on st.sno = sc1.sno  
  207.  where sc1.cno in (select sc.cno from t_score sc where sc.sno = '1')  
  208.  group by st.sno, st.sname;  
  209.   
  210.   
  211.   
  212. --(十五)列出既学过"1"号课程,又学过"2"号课程的所有学生姓名  
  213. --1.将成绩表和课程表作关联,在关联条件中作过滤查询出既选过课程'1'又选过课程'2'的学生的学号,注意看 co.cno in ('1', '2')和having count(distinct sc.cno) = 2 的位置.  
  214. --2.在学生表中根据步骤1的结果作过滤查询出学生的基本信息.  
  215. --方法一:  
  216. --sql86  
  217. select st.sno, st.sname  
  218.   from t_student st,  
  219.        (select sc.sno  
  220.           from t_score sc, t_course co  
  221.          where sc.cno = co.cno  
  222.            and co.cno in ('1''2')  
  223.          group by sc.sno  
  224.         having count(distinct sc.cno) = 2) t1  
  225.  where st.sno = t1.sno;  
  226.    
  227.  --sql92  
  228.  select st.sno, st.sname  
  229.   from t_student st join   
  230.        (select sc.sno  
  231.           from t_score sc join t_course co  
  232.          on sc.cno = co.cno  
  233.            and co.cno in ('1''2')  
  234.          group by sc.sno  
  235.         having count(distinct sc.cno) = 2) t1  
  236.  on st.sno = t1.sno;  
  237.    
  238.  --方法二:  
  239.  --sql86  
  240.  select st.sno, st.sname  
  241.    from t_student st  
  242.   where st.sno in (select sc.sno  
  243.                      from t_score sc, t_course co  
  244.                     where sc.cno = co.cno  
  245.                       and co.cno in ('1''2')  
  246.                     group by sc.sno  
  247.                    having count(distinct sc.cno) = 2);  
  248.    
  249. --sql92   
  250.   select st.sno, st.sname  
  251.     from t_student st  
  252.    where st.sno in (select sc.sno  
  253.                       from t_score sc  
  254.                       join t_course co  
  255.                         on sc.cno = co.cno  
  256.                        and co.cno in ('1''2')  
  257.                      group by sc.sno  
  258.                     having count(distinct sc.cno) = 2);  
  259.    
  260.    
  261.    
  262.  --(十六)查询至少学过学号为"1"的同学所有门课的同学学号和姓名  
  263.  --1.查询出'1'号同学学习的全部课程.  
  264.  --2.查询出'1'号同学学习全部课程的数量.  
  265.  --3.将课程表和成绩表做关联,在关联表中查询出学生的学号,关联条件中加入过滤条件[课程号在步骤1查询结果范围内],过滤条件中加入数量等级步骤2中得到的数量.  
  266.  --4.在学生表中查询步骤3中的学号的学生的基本信息.  
  267. select st.sno, st.sname  
  268.   from t_student st  
  269.  where st.sno in  
  270.        (select sc.sno  
  271.           from t_score sc  
  272.           join t_course co  
  273.             on sc.cno = co.cno  
  274.            and co.cno in (select sc.cno from t_score sc where sc.sno = '1')  
  275.          group by sc.sno  
  276.         having count(distinct sc.cno) = (select count(distinct sc.cno)  
  277.                                           from t_score sc  
  278.                                          where sc.sno = '1'))  
  279.                                            
  280.     
  281.                                            
  282.  --(十七)查询和"6"号同学学习的课程完全相同的同学的学号和姓名  
  283.  --分析:要查询与6号同学完全相同的课程的学生信息,等价于学过6号同学的学过的所有课程并且选课数量与6同学选课数量相等.  
  284.  --方法一:   
  285.  --1.查询出'1'号同学学习的全部课程.  
  286.  --2.查询出'1'号同学学习全部课程的数量.  
  287.  --3.将课程表和成绩表做关联,在关联表中查询出学生的学号和选课数量,记作 t2,关联条件中加入过滤条件[课程号在步骤1查询结果范围内],过滤条件中加入数量等级步骤2中得到的数量.  
  288.  --4.在成绩表中查询出学号和每个学生选课数量.得到结果记作: t1  
  289.  --5.将步骤3中的t2和步骤4中的t1通过学生学号关联,添加过滤条件,t1中的选课数量等于t2中的选课数量.  
  290.  --6.在学生表中查询不步骤5的学生学号的基本信息.  
  291.  select st.sno, st.sname  
  292.    from t_student st  
  293.   where st.sno in  
  294.         (select t1.sno  
  295.            from (select sc_a.sno, count(distinct sc_a.cno) num_outer  
  296.                    from t_score sc_a  
  297.                   group by sc_a.sno) t1  
  298.            join (select sc.sno, count(distinct sc.cno) num_inner  
  299.                   from t_score sc  
  300.                   join t_course co  
  301.                     on sc.cno = co.cno  
  302.                    and co.cno in  
  303.                        (select sc.cno from t_score sc where sc.sno = '6')  
  304.                  group by sc.sno  
  305.                 having count(distinct sc.cno) = (select count(distinct sc.cno)  
  306.                                                   from t_score sc  
  307.                                                  where sc.sno = '6')) t2  
  308.              on t1.sno = t2.sno  
  309.           where t1.num_outer = t2.num_inner);  
  310.             
  311.     
  312.             
  313.  --(十八)列出"1"号课成绩比"2"号课成绩高的所有学生的学号及其"1"号课和"2"号课的成绩  
  314.  --1.将学生表和课程表作两次关联,一次关联用于取该学生课程'1'的成绩,另一次关联用于取该学生课程'2'的成绩.  
  315.  --sql86  
  316. select st.sno, st.sname, sc_a.grade, sc_b.grade  
  317.   from t_student st, t_score sc_a, t_score sc_b  
  318.  where sc_a.cno = '1'  
  319.    and sc_b.cno = '2'  
  320.    and st.sno = sc_a.sno  
  321.    and st.sno = sc_b.sno  
  322.    and sc_a.grade > sc_b.grade  
  323.      
  324.  --sql92  
  325. select st.sno, st.sname, sc_a.grade, sc_b.grade  
  326.   from t_student st  
  327.   join t_score sc_a  
  328.     on st.sno = sc_a.sno  
  329.   join t_score sc_b  
  330.     on st.sno = sc_b.sno  
  331.  where sc_a.cno = '1'  
  332.    and sc_b.cno = '2'  
  333.    and sc_a.grade > sc_b.grade  
  334.      
  335.   
  336.   
  337. --(十九)查询所有同学的学号、姓名、选课数、总成绩  
  338. select st.sno, st.sname, count(sc.cno), sum(sc.grade)  
  339.   from t_student st, t_score sc  
  340.  where st.sno = sc.sno  
  341.  group by st.sno, st.sname;  
  342.   
  343.   
  344.   
  345. --(二十)查询课程成绩小于60分的同学的学号,姓名,课程名,成绩  
  346. --下面两条sql虽然结果相同,但意义不同,注意理解一下哦.  
  347. --1.将学生表,课程表,成绩表作关联  
  348. --2.对关联后的结果作过滤,过滤出成绩小于60的学生基本信息.  
  349. select st.sno, st.sname, co.cname, sc.grade  
  350.   from t_score sc  
  351.   join t_student st  
  352.     on sc.sno = st.sno  
  353.   join t_course co  
  354.     on sc.cno = co.cno  
  355.  where sc.grade < 60  
  356.   
  357. --1.将学生表,课程表,成绩表作关联,在关联条件中过滤成绩小于60.  
  358.  select st.sno, st.sname, co.cname, sc.grade  
  359.   from t_score sc  
  360.   join t_student st  
  361.     on sc.sno = st.sno  
  362.   join t_course co  
  363.     on sc.cno = co.cno  
  364. and sc.grade <60  
  365.   
  366.   
  367.   
  368. --(二十一)按平均成绩从到低显示所有学生的"JAVA程序设计"、"J2EE从入门到精通"、"EJB及设计模式"三门的课程成绩,  
  369. --并按如下形式显示: 学生ID,姓名,JAVA程序设计,J2EE从入门到精通,EJB及设计模式,有效课程数,有效课程平均分  
  370. --1.将成绩表和课程表关联得到结果记作: t1, 关联时的条件选择只统计以上三门课程.  
  371. --2.按题目中的要求组织统计结果.  
  372. select st.sno,  
  373.        st.sname,  
  374.        sum(decode(t1.cname, 'JAVA程序设计', t1.grade)) JAVA程序设计,  
  375.        sum(decode(t1.cname, 'J2EE从入门到精通', t1.grade)) J2EE从入门到精通,  
  376.        sum(decode(t1.cname, 'EJB及设计模式', t1.grade)) EJB及设计模式,  
  377.        count(distinct t1.grade) 有效课程数,  
  378.        avg(t1.grade) 有效课程平均分  
  379.   from t_student st  
  380.   join (select *  
  381.           from t_score sc  
  382.           join t_course co  
  383.             on sc.cno = co.cno  
  384.            and co.cname in  
  385.                ('JAVA程序设计''J2EE从入门到精通''EJB及设计模式')) t1  
  386.     on st.sno = t1.sno  
  387.  group by st.sno, st.sname  
  388.      
  389.  --将decode可以换成case when 第一种形式  
  390.  select st.sno,  
  391.         st.sname,  
  392.         sum(case t1.cname  
  393.               when 'JAVA程序设计' then  
  394.                t1.grade  
  395.             end) JAVA程序设计,  
  396.          sum(case t1.cname  
  397.               when 'J2EE从入门到精通' then  
  398.                t1.grade  
  399.             end) J2EE从入门到精通,  
  400.              sum(case t1.cname  
  401.               when 'EJB及设计模式' then  
  402.                t1.grade  
  403.             end) EJB及设计模式,  
  404.         count(distinct t1.grade) 有效课程数,  
  405.         avg(t1.grade) 有效课程平均分  
  406.    from t_student st  
  407.    join (select *  
  408.            from t_score sc  
  409.            join t_course co  
  410.              on sc.cno = co.cno  
  411.             and co.cname in  
  412.                 ('JAVA程序设计''J2EE从入门到精通''EJB及设计模式')) t1  
  413.      on st.sno = t1.sno  
  414.   group by st.sno, st.sname  
  415.     
  416.     
  417.  --将decode可以换成case when 第二种形式  
  418.   select st.sno,  
  419.          st.sname,  
  420.          sum(case  
  421.                when t1.cname = 'JAVA程序设计' then  
  422.                 t1.grade  
  423.              end) JAVA程序设计,  
  424.          sum(case  
  425.                when t1.cname = 'J2EE从入门到精通' then  
  426.                 t1.grade  
  427.              end) J2EE从入门到精通,  
  428.          sum(case  
  429.                when t1.cname = 'EJB及设计模式' then  
  430.                 t1.grade  
  431.              end) EJB及设计模式,  
  432.          count(distinct t1.grade) 有效课程数,  
  433.          avg(t1.grade) 有效课程平均分  
  434.     from t_student st  
  435.     join (select *  
  436.             from t_score sc  
  437.             join t_course co  
  438.               on sc.cno = co.cno  
  439.              and co.cname in  
  440.                  ('JAVA程序设计''J2EE从入门到精通''EJB及设计模式')) t1  
  441.       on st.sno = t1.sno  
  442.    group by st.sno, st.sname  
  443.    
  444.    
  445. --(二十二)查询各科成绩最高和最低的分:以如下形式显示:课程ID,课程名,最高分,最低分  
  446. select sc.cno, co.cname, max(grade), min(grade)  
  447.   from t_score sc  
  448.   join t_course co  
  449.     on sc.cno = co.cno  
  450.  group by sc.cno, co.cname  
  451.   
  452.   
  453. --(二十三)按各科平均成绩从低到高和及格率的百分数从高到低顺序   
  454. --1.在成绩表中查出课程号,平均成绩,课程人数,记作 : t1  
  455. --2.在成绩表中查出课程号,及格的课程人数,记作 : t2  
  456. --3.将步骤1中的成绩和步骤2中的课程2关联,查出所要的结果并排序.  
  457. select t1.cno, t1.avg_num 平均成绩, (count_num1 / count_num) * 100 及格率  
  458.   from (select sc.cno, avg(grade) avg_num, count(distinct sc.sno) count_num  
  459.           from t_score sc  
  460.          group by sc.cno) t1  
  461.   join (select sc1.cno, count(distinct sc1.sno) count_num1  
  462.           from t_score sc1  
  463.          where sc1.grade > 60  
  464.          group by sc1.cno) t2  
  465.     on t1.cno = t2.cno  
  466.  order by t1.avg_num asc, 及格率 desc  
  467.    
  468.    
  469. --(二十四)统计各科成绩,各分数段人数:课程ID,课程名称,[100-90]优,[90-80]良,[80-70]中,[70-60]一般,[<60]不及格  
  470. --1.在成绩表中根据成绩值分段  
  471. --2.将步骤1中的结果与课程表关联.  
  472. select sc.cno,co.cname,  
  473.        sum(case  
  474.              when sc.grade > 90 then  
  475.               1  
  476.            end) 优,  
  477.        sum(case  
  478.              when sc.grade > 80 and sc.grade < 90 then  
  479.               1  
  480.            end) 良,  
  481.        sum(case  
  482.              when sc.grade > 70 and sc.grade < 80 then  
  483.               1  
  484.            end) 中,  
  485.        sum(case  
  486.              when sc.grade > 60 and sc.grade < 70 then  
  487.               1  
  488.            end) 一般,  
  489.        sum(case  
  490.              when sc.grade < 60 then  
  491.               1  
  492.            end) 不及格  
  493.   from t_score sc join t_course co on sc.cno = co.cno  
  494.  group by sc.cno,co.cname  
  495.   
  496. --(二十五)查询学生平均成绩及其名次  
  497. select st.sno, st.sname, avg(sc.grade) avg_num  
  498.   from t_score sc  
  499.   join t_student st  
  500.     on sc.sno = st.sno  
  501.  group by st.sno, st.sname  
  502.  order by avg_num desc  
  503.   
  504.   
  505.   
  506. --(二十六)查询课程号分别为1,2,3的课程,成绩前三名的学生基本信息:(不考虑成绩并列情况)  
  507. --方法一:  
  508. --1.分别查出1,2,3各自的前3名的学生的学号,并用union all将结果集关联.  
  509. --2.在学生表中查询步骤1中查到的id的学生的基本信息.  
  510. select *  
  511.   from t_student  
  512.  where sno in (select t1.sno  
  513.                  from (select sc1.*  
  514.                          from t_score sc1  
  515.                         where sc1.cno = 1  
  516.                         order by sc1.grade desc) t1  
  517.                 where rownum < 4  
  518.                union all  
  519.                select t1.sno  
  520.                  from (select sc1.*  
  521.                          from t_score sc1  
  522.                         where sc1.cno = 2  
  523.                         order by sc1.grade desc) t1  
  524.                 where rownum < 4  
  525.                union all  
  526.                select t1.sno  
  527.                  from (select sc1.*  
  528.                          from t_score sc1  
  529.                         where sc1.cno = 3  
  530.                         order by sc1.grade desc) t1  
  531.                 where rownum < 4)  
  532.   
  533. --方法二:  
  534.  --rank() over(Partition .. order by ...) 是按照某个字段的值进行分组并编号  
  535. select t1.cno, t1.sno, t1.grade, r  
  536.   from (select sc.sno,  
  537.                sc.cno,  
  538.                sc.grade,  
  539.                rank() over(partition by sc.cno order by grade desc) r  
  540.           from t_score sc) t1  
  541.  where r < 4  
  542.    and t1.cno in (1, 2, 3)  
  543.  order by t1.cno, t1.sno, r;  
  544.   
  545.   
  546.  --(二十七)查询各科成绩前三名的记录(不考虑成绩并列情况)  
  547.  --rank() over(Partition .. order by ...) 是按照某个字段的值进行分组并编号  
  548. select t1.cno, t1.sno, t1.grade, r  
  549.   from (select sc.sno,  
  550.                sc.cno,  
  551.                sc.grade,  
  552.                rank() over(partition by sc.cno order by grade desc) r  
  553.           from t_score sc) t1  
  554.  where r < 4  
  555.  order by t1.cno, t1.sno, r;  
  556.     
  557. </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 语句。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值