找回密码
 立即注册
首页 业界区 安全 Oracle SQL经典练习50题 | 附答案

Oracle SQL经典练习50题 | 附答案

昆拗干 昨天 20:05

  • 建表
建表语句可以先根据自己对表关系进行设计,自定义发挥,写法不局限。
  1. -- 学生表student()
  2. create table student(
  3.        stu_id number generated always as identity,
  4.        stu_name varchar2(80) not null,
  5.        stu_birthday date,
  6.        stu_sex varchar(2),
  7.        primary key(stu_id),
  8.        check(stu_sex in ('m','f'))
  9. );
  10. --课程表course(id,课程名,老师id)
  11. create table course(
  12.        cou_id number generated always as identity primary key ,
  13.        cou_name varchar2(80),
  14.        tea_id number,
  15.        constraint fk_tea_id foreign key (tea_id) references teacher(tea_id)
  16.    
  17. );
  18. --教师表teacher(id,名字)
  19. create table teacher(
  20.        tea_id number generated always as identity primary key,
  21.        tea_name varchar2(80)
  22. );
  23. --成绩表score
  24. create table score(
  25.        sco_id number generated always as identity primary key,
  26.        stu_id number,
  27.        cou_id number,
  28.        score number
  29.       
  30. );
复制代码

  • 插入数据
以下只是初步的一个数据插入,并非一层不变,可以根据后续条件的需求再来调整。
  1. -- 学生信息
  2. INSERT INTO STUDENT VALUES(Default, '赵雷' , to_date('1990-01-01','YYYY-MM-DD') , 'm');
  3. INSERT INTO STUDENT VALUES(Default, '钱电' , to_date('1990-12-21','YYYY-MM-DD') , 'm');
  4. INSERT INTO STUDENT VALUES(Default, '孙风' , to_date('1990-12-20','YYYY-MM-DD') , 'm');
  5. INSERT INTO STUDENT VALUES(Default, '李云' , to_date('1990-12-06','YYYY-MM-DD') , 'm');
  6. INSERT INTO STUDENT VALUES(Default, '周梅' , to_date('1991-12-01','YYYY-MM-DD') , 'f');
  7. INSERT INTO STUDENT VALUES(Default, '吴兰' , to_date('1992-01-01','YYYY-MM-DD') , 'f');
  8. INSERT INTO STUDENT VALUES(Default, '郑竹' , to_date('1989-01-01','YYYY-MM-DD') , 'f');
  9. INSERT INTO STUDENT VALUES(Default, '张三' , to_date('2017-12-20','YYYY-MM-DD') , 'f');
  10. INSERT INTO STUDENT VALUES(Default, '李四' , to_date('2017-12-25','YYYY-MM-DD') , 'f');
  11. INSERT INTO STUDENT VALUES(Default, '李四' , to_date('2012-06-06','YYYY-MM-DD') , 'f');
  12. INSERT INTO STUDENT VALUES(Default, '赵六' , to_date('2013-06-13','YYYY-MM-DD') , 'f');
  13. INSERT INTO STUDENT VALUES(Default, '孙七' , to_date('2014-06-01','YYYY-MM-DD') , 'f');
  14. select * from STUDENT;
  15. -- 课程信息
  16. INSERT INTO COURSE VALUES(Default, '语文' , 2);
  17. INSERT INTO COURSE VALUES(Default, '数学' , 1);
  18. INSERT INTO COURSE VALUES(Default, '英语' , 3);
  19. select * from COURSE;
  20. -- 教师信息
  21. INSERT INTO TEACHER VALUES(Default, '张三');
  22. INSERT INTO TEACHER VALUES(Default, '李四');
  23. INSERT INTO TEACHER VALUES(Default, '王五');
  24. select * from teacher;
  25. -- 成绩
  26. INSERT INTO SCORE VALUES(default,1 , 1 , 80);
  27. INSERT INTO SCORE VALUES(default,1 , 2 , 90);
  28. INSERT INTO SCORE VALUES(default,1 , 3 , 99);
  29. INSERT INTO SCORE VALUES(default,2 , 1 , 70);
  30. INSERT INTO SCORE VALUES(default,2 , 2 , 60);
  31. INSERT INTO SCORE VALUES(default,2 , 3 , 80);
  32. INSERT INTO SCORE VALUES(default,3 , 1 , 80);
  33. INSERT INTO SCORE VALUES(default,3 , 2 , 80);
  34. INSERT INTO SCORE VALUES(default,3 , 3 , 80);
  35. INSERT INTO SCORE VALUES(default,4 , 1 , 50);
  36. INSERT INTO SCORE VALUES(default,4 , 2, 30);
  37. INSERT INTO SCORE VALUES(default,4, 3 , 20);
  38. INSERT INTO SCORE VALUES(default,5 , 1, 76);
  39. INSERT INTO SCORE VALUES(default,5, 2, 87);
  40. INSERT INTO SCORE VALUES(default,6 , 1, 31);
  41. INSERT INTO SCORE VALUES(default,6 , 3, 34);
  42. INSERT INTO SCORE VALUES(default,7 , 2 , 89);
  43. INSERT INTO SCORE VALUES(default,7, 3 , 98);
复制代码

  • SQL习题
以下写法只是个人见解,如有问题欢迎指出,相互学习,一起进步。
  1. -- 1.查询"数学 "课程比" 语文 "课程成绩高的学生的信息及课程分数
  2. select stu.*, c.couid1, c.sco1,  c.couid2, c.sco2 from student stu ,
  3. (
  4. select a.stu_id, a.cou_id as couid1, a.score as sco1, b.cou_id as couid2, b.score as sco2 from
  5. (select * from score where cou_id = 2) a,
  6. (select * from score where cou_id = 1) b
  7. where a.stu_id = b.stu_id and a.score > b.score
  8. )c
  9. where stu.stu_id = c.stu_id
  10. -- 优化:
  11. with
  12. --数学成绩临时表
  13. math_score as (
  14. select *from score where cou_id = 2
  15. ),
  16. --语文成绩临时表
  17. chinese_score as (
  18. select *from score where cou_id = 1
  19. )
  20. select * from
  21. student stu,math_score ms,chinese_score cns
  22. where
  23. stu.stu_id = ms.stu_id
  24. and stu.stu_id = cns.stu_id
  25. and ms.score > cns.score
  26. -- 1.1 查询同时存在" 数学 "课程和" 语文 "课程的情况
  27. with
  28. math_score as (
  29. select * from score sco where sco.cou_id = 2
  30. ),
  31. chinese_score as (
  32. select * from score sco where sco.cou_id = 1
  33. )
  34. select * from
  35. math_score ms, chinese_score cns
  36. where
  37. ms.stu_id = cns.stu_id
  38. -- 1.2 查询存在" 数学 "课程但可能不存在" 语文 "课程的情况(不存在时显示为 null )
  39. select * from
  40. (select * from score sco where sco.cou_id = 2) m
  41. left join
  42. (select * from score sco where sco.cou_id = 1) c
  43. on m.stu_id = c.stu_id
  44. -- 1.3 查询不存在" 数学 "课程但存在" 语文 "课程的情况
  45. --方式1
  46. select * from score sco where sco.cou_id = 1
  47. and sco.stu_id not in
  48. (select sco.stu_id from score sco where sco.cou_id = 2)
  49. --方式2
  50. select * from score sc where sc.cou_id = 1
  51. and not exists
  52. (
  53. select 1 from score scs where sc.stu_id = scs.stu_id and scs.cou_id = 2
  54. )
  55. -- 2.查询平均成绩大于等于 60 分的同学的学生编号和学生姓名和平均成绩
  56. select stu.stu_id, stu.stu_name, round(avg(sco.score),2) as avg_sco from student stu, score sco
  57. where stu.stu_id = sco.stu_id
  58. group by stu.stu_id, stu.stu_name
  59. having avg(sco.score) > 60<br><br>
  60. -- 3.查询在 成绩 表存在成绩的学生信息
  61. select distinct stu.* from student stu, score sco
  62. where stu.stu_id = sco.stu_id
  63. -- 4.查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩(没成绩的显示为 null )
  64. select stu.stu_id, stu.stu_name, count(sco.cou_id) as count_cou , sum(sco.score) as sun_score from student stu
  65. left join score sco
  66. on stu.stu_id = sco.stu_id
  67. group by stu.stu_id, stu.stu_name
  68. order by sum(sco.score)
  69. -- 4.1 查有成绩的学生信息
  70. select * from student stu
  71. right join score sco
  72. on stu.stu_id = sco.stu_id
  73. -- 5.查询「李」姓老师的数量
  74. select * from teacher tea where tea.tea_name like '李%'
  75. -- 6.查询学过「张三」老师授课的同学的信息
  76. select * from student stu,score sco
  77. where stu.stu_id = sco.stu_id
  78. and sco.cou_id in
  79. (select cou.cou_id from course cou where cou.tea_id = (select tea.tea_id from teacher tea where tea.tea_name = '张三'))
  80. --优化
  81. select * from student stu
  82. join score sco on stu.stu_id = sco.stu_id
  83. join course cou on sco.cou_id = cou.cou_id
  84. join teacher tea on cou.tea_id = tea.tea_id
  85. where tea.tea_name = '张三'
  86. -- 7.查询没有学全所有课程的同学的信息
  87. select * from student stu
  88. left join score sco
  89. on stu.stu_id = sco.stu_id
  90. where stu.stu_id not in
  91. (select sco.stu_id from score sco group by sco.stu_id having count(cou_id) >= 3)
  92. --优化
  93. select stu.stu_id, stu.stu_name from student stu
  94. left join score sco
  95. on stu.stu_id = sco.stu_id
  96. group by stu.stu_id, stu.stu_name
  97. having count(sco.cou_id) < (select count(*) from course)
  98. order by stu.stu_id
  99. -- 8.查询至少有一门课与学号为" 01 "的同学所学相同的同学的信息
  100. select stu.stu_id, stu.stu_name, sco.cou_id from student stu
  101. join score sco
  102. on stu.stu_id = sco.stu_id
  103. where sco.cou_id in (select sco.cou_id from score sco where sco.stu_id = 1)
  104. order by stu.stu_id
  105. -- 9.查询和" 01 "号的同学学习的课程 完全相同的其他同学的信息
  106. select stu.stu_id, stu.stu_name from score sco
  107. join student stu on sco.stu_id = stu.stu_id
  108. where stu.stu_id != 1
  109. group by stu.stu_id, stu.stu_name
  110. having count(*) = (select count(*) from score where stu_id = 1)
  111. AND NOT EXISTS (
  112.         SELECT 1
  113.         FROM score s1
  114.         WHERE s1.stu_id = 1
  115.         AND s1.cou_id NOT IN (
  116.             SELECT cou_id
  117.             FROM score s2
  118.             WHERE s2.stu_id = stu.stu_id
  119.         )
  120.     );
  121. -- 10.查询没学过"张三"老师讲授的任一门课程的学生姓名
  122. select * from student stu
  123. where stu.stu_id not in
  124. (select sco.stu_id from score sco
  125. join course cou on sco.cou_id = cou.cou_id
  126. join teacher tea on cou.tea_id = tea.tea_id
  127. where tea.tea_name = '张三')
  128. --优化
  129. select * from student stu
  130. where not exists
  131. (
  132. select 1 from score sco
  133. join course cou on sco.cou_id = cou.cou_id
  134. join teacher tea on cou.tea_id = tea.tea_id
  135. where tea.tea_name = '张三'
  136. and sco.stu_id = stu.stu_id
  137. )
  138. -- 11.查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
  139. select stu.stu_id, stu.stu_name, round(avg(sco.score),2) from student stu
  140. join score sco
  141. on stu.stu_id = sco.stu_id
  142. where stu.stu_id in
  143. (
  144. select sco.stu_id from score sco
  145. where sco.score < 60
  146. group by sco.stu_id
  147. having count(*) >= 2
  148. )
  149. group by stu.stu_id, stu.stu_name;
  150. --优化1
  151. select
  152. stu.stu_id, stu.stu_name, round(avg(sco.score),2) as avg_score
  153. from
  154. student stu
  155. join
  156. score sco on stu.stu_id = sco.stu_id
  157. where Exists
  158. (
  159. select 1
  160. from score sco
  161. where sco.stu_id = stu.stu_id
  162. and sco.score < 60
  163. group by sco.stu_id
  164. having count(*) >= 2
  165. )
  166. group by
  167. stu.stu_id, stu.stu_name;
  168. --优化2
  169. with bad_stu as (
  170. select sco.stu_id from score sco
  171. where sco.score < 60
  172. group by sco.stu_id
  173. having count(*) >= 2
  174. )
  175. select stu.stu_id, stu.stu_name, round(avg(sco.score),2) from student stu
  176. join score sco
  177. on stu.stu_id = sco.stu_id
  178. where stu.stu_id in
  179. (
  180. select stu_id from bad_stu
  181. )
  182. group by stu.stu_id, stu.stu_name;
  183. -- 12.检索" 数学 "课程分数小于 60,按分数降序排列的学生信息
  184. select * from score sco
  185. join course cou on sco.cou_id = cou.cou_id
  186. where cou.cou_name = '数学'
  187. and sco.score < 60
  188. order by sco.score desc -- order by 默认是asc 升序,降序为 desc
  189. -- 13.按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
  190. with avg_score as (
  191. select sco.stu_id, round(avg(sco.score),2) as avg_sco from score sco
  192. group by sco.stu_id
  193. )
  194. select stu.stu_id, stu.stu_name, sco.cou_id, sco.score, avgsco.avg_sco from score sco
  195. join student stu on sco.stu_id = stu.stu_id
  196. join avg_score avgsco on stu.stu_id = avgsco.stu_id
  197. order by avgsco.avg_sco desc, sco.score DESC;
  198. --优化
  199. select
  200.       stu.stu_id, stu.stu_name, sco.cou_id, sco.score, round(avg(sco.score)over(partition by stu.stu_id),2) as avg_sco
  201. from
  202.       score sco
  203. join student stu on sco.stu_id = stu.stu_id
  204. order by avg_sco desc, sco.score desc
  205. -- 14.查询各科成绩最高分、最低分和平均分:
  206. select
  207.    sco.cou_id, cou.cou_name, max(sco.score)as max_sco, min(sco.score) as min_sco, round(avg(sco.score),2) as avg_sco
  208. from score sco
  209. join course cou on sco.cou_id = cou.cou_id
  210. group by sco.cou_id, cou.cou_name
  211. -- 15.以如下形式显示:课程 ID,课程 name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率
  212. /*
  213.   及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90
  214.   要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
  215.   按各科成绩进行排序,并显示排名, Score 重复时保留名次空缺
  216. */
  217. with score_stats as
  218. (
  219. select
  220.    sco.cou_id, cou.cou_name, count(*) as stu_count, max(sco.score)as max_sco, min(sco.score) as min_sco, round(avg(sco.score),2) as avg_sco,
  221.    --及格人数
  222.    sum(case when sco.score >= 60 then 1 else 0 end) as pass_count,
  223.    --中等人数
  224.    sum(case when sco.score >= 70 and sco.score < 80 then 1 else 0 end) as mid_count,
  225.    --优良人数
  226.    sum(case when sco.score >= 80 and sco.score < 90 then 1 else 0 end) as good_count,
  227.    --优秀人数
  228.    sum(case when sco.score >= 90 then 1 else 0 end) as excellent_count
  229. from score sco
  230. join course cou on sco.cou_id = cou.cou_id
  231. group by sco.cou_id, cou.cou_name
  232. )
  233. select
  234. scos.cou_id,
  235. scos.cou_name,
  236. scos.stu_count,
  237. scos.max_sco,
  238. scos.min_sco,
  239. scos.avg_sco,
  240.   -- 计算比率
  241. round((scos.pass_count / scos.stu_count) * 100, 2) as pass_rate,
  242. round((scos.mid_count / scos.stu_count) * 100, 2) as mid_rate,
  243. round((scos.good_count / scos.stu_count) * 100, 2) as good_rate,
  244. round((scos.excellent_count / scos.stu_count) * 100, 2) as excellent_rate,
  245. -- 按各科平均成绩进行排名,
  246. rank()over(order by avg_sco desc) as rank_no
  247. from
  248. score_stats scos
  249. order by
  250. scos.stu_count desc, scos.cou_id asc
  251. -- 15.1 按各科成绩进行排序,并显示排名, Score 重复时合并名次
  252. select sco.*, rank()over(partition by sco.cou_id order by sco.score desc) as rank_by_score from score sco
  253. -- 16.查询学生的总成绩,并进行排名,总分重复时保留名次空缺
  254. select
  255. stu.stu_id, stu.stu_name, coalesce(sum(sco.score),0) as sum_sco, rank()over(order by coalesce(sum(sco.score),0) desc ) as rank_no
  256. from
  257. score sco
  258. join
  259. student stu
  260. on
  261. sco.stu_id = stu.stu_id
  262. group by
  263. stu.stu_id, stu.stu_name
  264. -- 16.1 查询学生的总成绩,并进行排名,总分重复时不保留名次空缺
  265. --rank(): 有并列,跳过,例如 1,1,3
  266. --dense_rank(): 有并列,不跳过,例如:1,1,2
  267. select
  268. stu.stu_id, stu.stu_name, coalesce(sum(sco.score),0) as sum_sco, dense_rank()over(order by coalesce(sum(sco.score),0) desc ) as rank_no
  269. from
  270. score sco
  271. join
  272. student stu
  273. on
  274. sco.stu_id = stu.stu_id
  275. group by
  276. stu.stu_id, stu.stu_name
  277. -- 17.统计各科成绩各分数段人数:课程编号,课程名称,[100-90],(90-70],(70-60],(60-0] 及所占百分比
  278. with score_rates as
  279. (
  280. select
  281. sco.cou_id,
  282. cou.cou_name,
  283. count(*) as stu_count,
  284. sum(case when sco.score >=0 and sco.score < 60 then 1 else 0 end) as notpass_count,
  285. sum(case when sco.score >=60 and sco.score < 70 then 1 else 0 end) as mid_count,
  286. sum(case when sco.score >=70 and sco.score < 90 then 1 else 0 end) as good_count,
  287. sum(case when sco.score >=90 and sco.score <= 100 then 1 else 0 end) as excellent_count
  288. from score sco
  289. join course cou on sco.cou_id = cou.cou_id
  290. group by sco.cou_id, cou.cou_name
  291. )
  292. select
  293. scos.cou_id,
  294. scos.cou_name,
  295. scos.stu_count,
  296. scos.notpass_count,
  297. scos.mid_count,
  298. scos.good_count,
  299. scos.excellent_count,
  300. --占比
  301. round((scos.notpass_count / scos.stu_count) * 100,2) ||'%' as  notpass_rate,
  302. round((scos.mid_count / scos.stu_count) * 100,2) ||'%' as  mid_rate,
  303. round((scos.good_count / scos.stu_count) * 100,2) ||'%' as  good_rate,
  304. round((scos.excellent_count / scos.stu_count) * 100,2) ||'%' as  excellent_rate
  305. from score_rates scos
  306. -- 18.查询各科成绩前三名的记录
  307. select * from
  308. (
  309.     select sco.*, dense_rank()over(partition by cou_id order by sco.score desc) as dense_rank_no from score sco
  310. )
  311. where dense_rank_no <= 3
  312. -- 19.查询每门课程被选修的学生数
  313. select
  314. sco.cou_id,
  315. cou.cou_name,
  316. count(*) as stu_count
  317. from score sco
  318. join course cou on sco.cou_id = cou.cou_id
  319. group by sco.cou_id, cou.cou_name
  320. -- 20.查询出只选修两门课程的学生学号和姓名
  321. select sco.stu_id, stu.stu_name from score sco
  322. join student stu on sco.stu_id = stu.stu_id
  323. group by sco.stu_id, stu.stu_name
  324. having count(sco.stu_id) = 2
  325. -- 21.查询男生、女生人数
  326. select stu.stu_sex, count(*) from student stu
  327. group by stu.stu_sex
  328. -- 22.查询名字中含有「风」字的学生信息
  329. select * from student stu
  330. where stu.stu_name like '%风%'
  331. -- 23.查询同名同性学生名单,并统计同名人数(错0
  332. select stu.stu_name, count(*) from student stu
  333. group by stu.stu_name
  334. having count(*) >= 2
  335. -- 24.查询 1990 年出生的学生名单
  336. --方式一:性能差,无法使用索引
  337. select * from student stu
  338. where to_char(stu.stu_birthday, 'yyyy') = '1990'
  339. -- 方式二:性能好,可以使用索引
  340. select * from student stu
  341. where stu.stu_birthday >= to_date('1990-01-01','yyyy-mm-dd')
  342. and stu.stu_birthday < to_date('1991-01-01','yyyy,mm-dd')
  343. --方式三:性能差,无法使用索引
  344. select * from student stu
  345. where extract(year from stu.stu_birthday) = '1990'
  346. -- 25.查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
  347. select sco.cou_id, round(avg(sco.score),2) as avg_sco from score sco
  348. group by sco.cou_id
  349. order by round(avg(sco.score),2) desc, sco.cou_id asc
  350. -- 26.查询平均成绩大于等于 85 的所有学生的学号、姓名和平均成绩
  351. select sco.stu_id,stu.stu_name, round(avg(sco.score),2) from score sco
  352. join student stu on sco.stu_id = stu.stu_id
  353. group by sco.stu_id, stu.stu_name
  354. having round(avg(sco.score),2) >= 85
  355. -- 27.查询课程名称为「数学」,且分数低于 60 的学生姓名和分数
  356. select stu.stu_id,stu.stu_name,sco.cou_id,sco.score from score sco
  357. join student stu on sco.stu_id = stu.stu_id
  358. join course cou on sco.cou_id = cou.cou_id
  359. where cou.cou_name = '数学'
  360. and score <60
  361. -- 28.查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)
  362. select * from student stu
  363. left join score sco on stu.stu_id = sco.stu_id
  364. -- 29.查询任何一门课程成绩在 70 分以上的姓名、课程名称和分数
  365. select stu.stu_id, stu.stu_name, cou.cou_id, cou.cou_name, sco. score from score sco
  366. join student stu on sco.stu_id = stu.stu_id
  367. join course cou on sco.cou_id = cou.cou_id
  368. where sco.score > 70
  369. -- 30.查询不及格的课程
  370. select sco.stu_id, sco.cou_id, cou.cou_name, sco.score from score sco
  371. join course cou on sco.cou_id = cou.cou_id
  372. where sco.score < 60
  373. -- 31.查询课程编号为 01 且课程成绩在 80 分以上的学生的学号和姓名
  374. select stu.stu_id, stu.stu_name, sco.cou_id, score from score sco
  375. join student stu on sco.stu_id = stu.stu_id
  376. where sco.cou_id = 1
  377. and sco.score > 80
  378. -- 32.求每门课程的学生人数
  379. -- 33.成绩不重复,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩
  380. select stu.stu_id, stu.stu_name, cou.cou_id, cou.cou_name, sco.score from score sco
  381. join course cou on sco.cou_id = cou.cou_id
  382. join teacher tea on cou.tea_id = tea.tea_id
  383. join student stu on sco.stu_id = stu.stu_id
  384. where tea.tea_name = '张三'
  385. order by sco.score desc
  386. FETCH FIRST 1 ROWS ONLY;
  387. --select * from score ;
  388. --update score sco set sco.score = 90 where sco.stu_id in (5,7) ;
  389. --34.成绩有重复的情况下,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩
  390. select stu.stu_id, stu.stu_name, cou.cou_id, cou.cou_name, sco.score from score sco
  391. join course cou on sco.cou_id = cou.cou_id
  392. join teacher tea on cou.tea_id = tea.tea_id
  393. join student stu on sco.stu_id = stu.stu_id
  394. where tea.tea_name = '张三'
  395. order by sco.score desc
  396. fetch first 1 rows with ties; -- 如果有多个最高分会全部显示出来
  397. -- 35.查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩
  398. with repeat_count as (
  399. select sco.cou_id, sco.score, count(*), sco.cou_id || '' || sco.score as cou_and_sco from score sco
  400. group by sco.cou_id, sco.score
  401. having count(*) >= 2
  402. )
  403. select stu.stu_id, stu.stu_name, sco.cou_id, sco.score from score sco
  404. join student stu on sco.stu_id = stu.stu_id
  405. where sco.cou_id || '' || sco.score in (select cou_and_sco from repeat_count )
  406. order by sco.cou_id, sco.score
  407. -- 拼接字符串存在隐患:sco.cou_id || '' || sco.score,如果cou_id 或 score 是null,整个拼接结果为null,导致匹配失败
  408. -- 性能问题:in在大数据中查询效率较低,且以上代码in子查询返回的是字符串拼接的结果,数据库无法有效利用索引
  409. -- 优化方案1:避免字符串拼接,Exist性能比in好      
  410. with repeat_count as (
  411. select sco.cou_id, sco.score, count(*), sco.cou_id || '' || sco.score as cou_and_sco from score sco
  412. group by sco.cou_id, sco.score
  413. having count(*) >= 2
  414. )
  415. select stu.stu_id, stu.stu_name, sco.cou_id, sco.score from score sco
  416. join student stu on sco.stu_id = stu.stu_id
  417. where exists
  418. (
  419.       select 1 from repeat_count rc  where sco.cou_id = rc.cou_id and sco.score = rc.score
  420. )
  421. order by sco.cou_id, sco.score;
  422. -- 优化方案2:使用count()over()函数,只需扫描score表一次,性能高,时候大数据场景
  423. select stu.stu_id,stu.stu_name,scos.cou_id, scos.score from
  424. (select sco.*, count(*)over(partition by sco.cou_id, sco.score) as repeat_count from score sco) scos
  425. join student stu on scos.stu_id = stu.stu_id
  426. where scos.repeat_count >= 2
  427. --优化方案3:in + 行构造器,语法简洁
  428. select
  429. stu.stu_id, stu.stu_name, sco.cou_id, sco.score
  430. from
  431. score sco
  432. join student stu on sco.stu_id = stu.stu_id
  433. where (sco.cou_id, sco.score) in
  434. (
  435.    select cou_id, score from score group by cou_id, score having count(*) >=2
  436. )
  437. ORDER BY sco.cou_id, sco.score;
  438. -- 36.查询每门功成绩最好的前两名
  439. with rank_score as
  440. (
  441. select sco.*, dense_rank()over(partition by sco.cou_id order by sco.score desc) as rank_no from score sco
  442. )
  443. select stu.stu_id,stu.stu_name,rsco.cou_id,rsco.score,rsco.rank_no from rank_score rsco
  444. join student stu on rsco.stu_id = stu.stu_id
  445. where rsco.rank_no <= 2
  446. -- 37.统计每门课程的学生选修人数(超过 5 人的课程才统计)。
  447. select sco.cou_id, count(*) as stu_count
  448. from score sco
  449. group by sco.cou_id
  450. having count(*) > 5
  451. -- 38.检索至少选修两门课程的学生学号
  452. select sco.stu_id, count(*) as stu_cou_count from score sco group by sco.stu_id having count(*) >=2
  453. -- 39.查询选修了全部课程的学生信息
  454. select sco.stu_id, stu.stu_name, count(*) as stu_cou_count from score sco
  455. join student stu on stu.stu_id = sco.stu_id
  456. group by sco.stu_id,stu.stu_name
  457. having count(*) = (select count(*) from course cou)
  458. -- 40.查询各学生的年龄,只按年份来算
  459. select stu.*,extract(year from sysdate)-extract(year from stu.stu_birthday) as age  from student stu
  460. --方式二:
  461. select stu.*,to_char(sysdate,'yyyy') - to_char(stu.stu_birthday,'yyyy') as age  from student stu
  462. -- 41.按照出生日期来算,当前月日 < 出生年月的月日则,年龄减一
  463. select stu.*, floor(months_between(sysdate,stu.stu_birthday)/12) as age  from student stu
  464. -- 42.查询本周过生日的学生
  465. --方案一:
  466. --逻辑:将学生的生日换成今年的日期,然后再判断该日期是否在本周一到周日内
  467. --select *from student;
  468. --update student set stu_birthday = to_date('1990-4-22','yyyy-mm-dd') where stu_id = 2
  469. select * from student stu
  470. where
  471. -- 将学生的生日转成今年的日期
  472. trunc(
  473. to_date
  474. (
  475. to_char(sysdate,'yyyy')||'-'||to_char(stu.stu_birthday,'mm-dd'),'yyyy-mm-dd'
  476. )
  477. )
  478. between
  479. trunc(sysdate,'IW') -- 本周的起始日期,周一
  480. and
  481. trunc(sysdate,'IW')+6; -- 本周的起始日期,周日
  482. --方案二:
  483. --逻辑:只关心月和日,学生的生日月日是否在本周内
  484. select * from student stu
  485. where
  486. to_char(stu.stu_birthday,'mm-dd')
  487. between
  488. to_char(trunc(sysdate,'IW'),'mm-dd')
  489. AND
  490. to_char(trunc(sysdate,'IW')+6,'mm-dd')
  491. -- 43.查询下周过生日的学生
  492. select * from student stu
  493. where
  494. -- 将学生的生日转成今年的日期
  495. trunc(
  496. to_date
  497. (
  498. to_char(sysdate,'yyyy')||'-'||to_char(stu.stu_birthday,'mm-dd'),'yyyy-mm-dd'
  499. )
  500. )
  501. between
  502. trunc(sysdate,'IW')+7 -- 本周的起始日期,周一
  503. and
  504. trunc(sysdate,'IW')+13; -- 本周的起始日期,周日
  505. -- 44.查询本月过生日的学生
  506. --方式1
  507. select * from student stu
  508. where
  509. extract(month from stu.stu_birthday) = extract(month from sysdate)
  510. --方式2
  511. select * from student stu
  512. where
  513. to_char(stu.stu_birthday,'mm') = to_char(sysdate,'mm')
  514. -- 45.查询下月过生日的学生
  515. select * from student stu
  516. where
  517. extract(month from stu.stu_birthday) = extract(month from sysdate)+1
复制代码
 

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册