SQL-Part7-索引与复习习题(学习第七天)

1.索引

1.1描述

用于加快查询速度,但会占用空间。

1.2二叉树(B_Tree)索引

(1)创建方式:
create index i_emp_ename on scott.emp(ename)
(2)描述
->i_emp_ename 为索引的名字, scott.emp(ename)为索引的内容。
->添加索引后,在查询scott.emp.ename会比原先快0.002~0.010s,对于数据量大的提升更多,但要注意一个列最多不能建立超过2个索引。

1.3位图索引

(1)创建方式:
create bitmap index i_emp_ename on scott.emp(ename)
(2)描述
和B_Tree索引类似,区别在于检索方式,位图只能将表分为两部分,进行检索,而B_Tree索引可以分成很多个二叉树,分别进行检索。

1.4反向键索引

(1)创建方式:
create index i_emp_ename on scott.emp(ename) reverse
(2)描述
反向进行检索,如:原本为‘A’->'Z',转换为‘Z’->'A'。

1.5删除检索

drop index i_emp_ename

1.6复合检索

create index i_emp_ename_job on scott.emp(ename,job)
注意:(1)检索ename,job、ename、job,name、都可以加速,而单独检索job不行。
(2)not、like、!=等等,会让索引失效。

1.7索引建立或使用的规则与建议

(1).如果对某大表进行筛选时,某列或某几列频繁出现在WHERE子句中,并且检索出的数 据低于总行数的15%(50%),应考虑在这些列上建立索引。
(2).如果对某大表进行排序时,某列或某几列频繁出现在ORDER BY子句中,应考虑在这些 列上建立索引。
(3).小表不要建立索引。
(4).对于含有空值的列,如果经常在查询时查询非空值,建议在该列上建立索引;如果经 常在查询时查询空值,建议在该列上建立基于函数的索引。
(5).为了提高表连接的性能,应在连接列上建立索引(建立一般普通的索引即可)
(6).索引是数据库的一种实体对象,级别类似于表,会占用内存空间,ORACLE会自动进行 索引维护,表和索引可以建立在不同的表空间。

1.8练习小测

--1.给emp表的ename列创建一个索引,建立索引前后时间对比
select e.ename from scott.emp e;--0.017-0.012
create index e_emp_ename on scott.emp(ename);
select e.ename from scott.emp e;--0.014-0.011
drop index e_emp_ename
--2.创建job和sal的复合索引,查询工资大于2000的MANAGER员工信息
create index e_emp_ename_job on scott.emp(sal,job);
select e.sal,e.job from scott.emp e where e.sal>=2000 and e.job ='MANAGER';
--3.查询所有人选修c002课程及格的情况,自己判断如何创建索引
create index s_sc_cno on sc(cno);
select * from sc s where s.cno='c002';
--4.使用小写函数来创建索引,查询带有m的员工信息
create index e_emp_ename on scott.emp(ename);
select * from scott.emp e where instr(lower(e.ename),'m',1,1)>0
--5.修改删除一个索引
create index e_emp_ename on scott.emp(ename);
alter index e_emp_ename rename to e_emp_ename1;

2.视图

2.1描述

视图实际上是一个或多个表的预定义查询,视图的使用方法和表一样。视图不存储数 据,他们只访问基表中的行。

2.2视图操作

(1)创建视图 :Create or replace view 视图名 as select * from 表名 with read only ;
(2)删除视图 :Drop view 视图名;
(3)注意:scott账号要使用system账号赋予权限才能创建视图 grant create any view to scott.

3.单元复习

--1、检索“c001”课程分数小于80,按分数降序排列的同学学号
select * from HRB.sc s where s.sno='s001' and s.score<80 order by s.cno
--2、查询各个课程及相应的选修人数
select 课程编号,c.cname 课程名字,选修人数 from (
select s.cno 课程编号,count(s.sno) 选修人数 from HRB.sc s  group by s.cno order by s.cno)
join HRB.COURSE c on 课程编号 =c.cno;
--3、按照不同老师编号分类显示课程列表,课程之间用逗号隔开
select c.tno,listagg(c.cname,',') 
within group(order by c.tno) from course c
group by c.tno
--4、查询各科成绩最高和最低的分:以如下形式显示:课程ID,最高分,最低分
select s.cno 课程ID,max(s.score) 最高分,min(s.score) 最低分 from sc s group by s.cno;
--5、查看成绩表信息,多加一列标注是否及格
select s.*,case when s.score >=80 then '合格'
              when s.score <80 then '不合格' end 是否及格
from sc s;
--6、查询出只选修了一门课程的全部学生的学号和姓名
select s.sno,s.sname from student s 
join sc on sc.sno=s.sno
group by s.sno,s.sname having count(sc.cno) =1;
--7、查询平均成绩大于85的所有学生的学号、姓名和平均成绩
select s.sno 学号,s.sname 姓名,avg(sc.score) 平均成绩 from sc 
left join student s on s.sno =sc.sno 
group by s.sno,s.sname having avg(sc.score)>85;
--8、统计各科成绩,各分数段人数:分数段为[100-85] a,[84-70] b,[69-60] c,[ <60] d
select r.cno,sum(r.a) A,sum(r.b) B,sum(r.c) C,sum(r.d) D from
(select sc.cno,
        case when sc.score between 85 and 100 then 1 else 0 end A,
        case when sc.score between 70 and 84 then 1 else 0 end B,
        case when sc.score between 60 and 69 then 1 else 0 end C,
        case when sc.score <60 then 1 else 0 end D
from sc) r group by r.cno;
--9、查询课程名称为“Oracle”,且分数低于60 的学生姓名和分数
select s.sname,sc.score from student s
join sc on sc.sno =s.sno 
join course c on c.cno =sc.cno
where lower(c.cname) ='oracle' and sc.score<60;
--10、查询所有学生的选课情况,选了多少门课程;
select s.sname,
       case when count(sc.cno) =0 then '没选课'
         else to_char(count(sc.cno)) end 选课情况
from student s
left join sc on sc.sno =s.sno
group by s.sname 
order by 选课情况;
--11、统计每门课程的学生选修人数(超过1人的课程才统计)。要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
select sc.cno 课程号,count(sc.sno) 选修人数 from sc 
group by sc.cno having count(sc.sno)>1
order by 选修人数 desc,sc.cno;
--12.向SC表中插入一些记录,这些记录要求符合以下条件:没有上过编号“c002”课程的同学学号、“c002”号课的平均成绩;4
insert into sc value(
select s.sno,'c002',(select avg(sc.score) from sc) 
from student s where s.sno not in(
select sc.sno from sc where sc.cno = 'c002')) 
--13、查询全部学生都选修的课程的课程号和课程名
select sc.sno,c.cno,c.cname from sc 
join course c on c.cno =sc.cno;
--14、查询没有学全所有课的同学的学号、姓名;
select s.sno,s.sname,count(sc.score) from sc 
join student s on s.sno =sc.sno
group by s.sno,s.sname having count(sc.score) <
(select count(1) from course);
--15、查询“c001”课程比“c002”课程成绩高的所有学生的学号;
select * from (select sc.sno,sc.score from sc where sc.cno ='c001') t
join (select sc.sno,sc.score from sc where sc.cno ='c002') t1 on t.sno =t1.sno
where t.score>t1.score
--16.将所有c001课程成绩低于平均成绩的同学的分数改为60分
select * from sc where sc.cno ='c001';
update sc set sc.score=60 
where(sc.score <(select avg(sc.score) from sc where sc.cno ='c001'))
--17.删除学习“谌燕”老师课的SC 表记录;
delete from sc 
where(sc.cno in (
select cno from course c where c.tno in(
(select t.tno from teacher t where t.tname ='谌燕'))))
/*18.创建dept1表获取scott.dept表数据,再使用insert...select插入一次
scott.dept表数据到detp1表,再使用删除语句删除重复数据*/
create table dept1 as select * from scott.dept
insert into dept1 value(select * from dept1)
select * from dept1;

delete from dept1 where(dept1.rowid  in
(select rowid from
(select d.*,row_number()over(partition by d.deptno order by d.deptno) r from dept1 d ) d
where d.r not in 1));

--恢复数据:85 line
select * from sc
--19、查询没学过“谌燕”老师课的同学的学号、姓名;
select s.sno,s.sname from student s
where s.sno not in(select sc.sno from sc 
left join course c on c.cno =sc.cno
left join teacher t on t.tno= c.tno
where t.tname  in '谌燕' group by sc.sno); 
--20、查询学过“c001”并且也学过编号“c002”课程的同学的学号、姓名;
select s.sno,s.sname,count(sc.cno) from student s
left join sc on sc.sno =s.sno
where sc.cno ='c001' or sc.cno ='c002'
group by s.sno,s.sname having count(sc.cno) =2;
--21、查询出每个学科排名第一名的学生姓名列表,包括课程编号,学生姓名,学生成绩
select sc.cno,s.sname,sc.score from student s
join sc on sc.sno = s.sno
where (sc.cno,sc.score) in
(select sc.cno,max(sc.score) from sc
group by sc.cno)
order by sc.cno;
--22、查询选修“谌燕”老师所授课程的学生中,成绩最高的学生姓名及其成绩

select * from 
(select s.sname,sc.score from student s
left join sc on sc.sno =s.sno
left join course c on c.cno =sc.cno
left join teacher t on t.tno= c.tno
where t.tname ='谌燕' order by sc.score desc) where rownum =1;
--23、查询学过“谌燕”老师所教的所有课的同学的学号、姓名;
select s.sno,s.sname from student s
left join sc on sc.sno =s.sno
left join course c on c.cno =sc.cno
left join teacher t on t.tno= c.tno
where t.tname ='谌燕' group by s.sno,s.sname 
having count(1)=(select count(1) from course c where c.tno =(select t.tno from teacher t where t.tname ='谌燕'));
--24、查询至少有一门课与学号为“s001”的同学所学相同的同学的学号和姓名
select s.sno,s.sname from student s
left join sc on sc.sno =s.sno
left join course c on c.cno =sc.cno
where sc.cno in (select sc.cno from sc where sc.sno ='s001') and s.sno !='s001' 
group by s.sno,s.sname;
--25、查询和“s001”号的同学学习的课程完全相同的其他同学学号和姓名

select sc.cno from sc where sc.sno ='s001'--序号
select max(rownum) from sc where sc.sno ='s001'--数量

select s.* from
(select sc.sno from (select sc.cno from sc where sc.sno ='s001') r
join sc on sc.cno =r.cno
group by sc.sno having count(sc.cno)=(select max(rownum) from sc where sc.sno ='s001')) k
join student s on s.sno =k.sno 
where s.sno != 's001';

你可能感兴趣的:(sql,数据库)