今天,主要是题目
--建表
--学生表:学号、姓名、性别、年龄
drop table t_student;
create table t_student(
sno varchar2(11) primary key,
sname varchar2(20) not null,
sex varchar2(3),
age number(3),
constraint c_1 check(sex in ('男','女'))
);
select * from t_student;
--教师表:编号、姓名
drop table t_teacher;
create table t_teacher(
tno varchar2(11) primary key,
tname varchar2(20) not null
);
select * from t_teacher;
--课程表:课程编号、课程名称、教师编号
drop table t_course;
create table t_course(
cno varchar2(5) primary key,
cname varchar2(20) not null,
tno varchar2(11)
);
select * from t_course;
--成绩表:学号、课程编号、成绩
drop table t_grade;
create table t_grade(
sno varchar2(11),
cno varchar2(5),
grade number(3)
);
--!!!这里成绩采用的数据类型不对,导致后面的bug
--!!!但是这里不影响知识点,就没有改回来了
select * from t_grade;
--插入可能用到的数据
insert into t_student values('s001','李元芳','男',11);
insert into t_student values('s002','马可波罗','男',20);
insert into t_student values('s003','孙尚香','女',16);
insert into t_student values('s004','公孙离','女',18);
insert into t_student values('s005','貂蝉','女',19);
insert into t_teacher values('t001','李白');
insert into t_teacher values('t002','韩信');
insert into t_course values('c001','打野教学','t001');
insert into t_course values('c002','刺客教学','t001');
insert into t_course values('c003','偷红教学','t001');
insert into t_course values('c004','反蓝教学','t002');
insert into t_course values('c005','刷龙教学','t002');
insert into t_grade values('s001','c001',80);
insert into t_grade values('s001','c002',59);
insert into t_grade values('s001','c004',60);
insert into t_grade values('s002','c001',70);
insert into t_grade values('s002','c002',50);
insert into t_grade values('s002','c003',40);
insert into t_grade values('s003','c003',50);
insert into t_grade values('s003','c005',70);
insert into t_grade values('s004','c001',55);
insert into t_grade values('s004','c002',50);
insert into t_grade values('s005','c002',90);
commit;
--1、查询“c001”课程比“c002”课程成绩高的所有学生的学号;
select g1.sno from t_grade g1,t_grade g2
where g1.sno = g2.sno
and g1.cno = 'c001'
and g2.cno = 'c002'
and g1.grade >g2.grade;
--测试数据需要
update t_grade set grade = 45 where cno = 'c001' and sno = 's004';
--2、查询平均成绩大于50 分的同学的学号和平均成绩;
select sno,avg(grade) from t_grade
group by sno
having avg(grade)>50;
--3、查询所有同学的学号、姓名、选课数、总成绩;
select g.sno,
(select sname from t_student where sno = g.sno) as "姓名",
count(1) as "选课数",sum(grade) as "总成绩"
from t_grade g
group by g.sno order by g.sno;
--4、查询没学过“李白”老师课的同学的学号、姓名;
update t_grade set cno = 'c004' where grade = 50 and sno = 's004';
select sno,sname from t_student where sno not in
(select distinct(sno) from t_grade where cno in
(select cno from t_course where tno in
(select tno from t_teacher where tname = '李白')
)
);
--李白教了哪些课,这些课哪些同学选了,除了这部分同学就是结果
--5、查询学过“c001”并且也学过编号“c002”课程的同学的学号、姓名
update t_grade set cno = 'c004' where grade = 50 and sno = 's004';
select * from t_grade;
select t1.sno,(select sname from t_student where sno = t1.sno) as "姓名"
from
(select sno from t_grade where cno = 'c001') t1,
(select sno from t_grade where cno = 'c002') t2
where t1.sno = t2.sno;
--6、查询学过“李白”老师所教的课的同学的学号、姓名;
select sno,sname from t_student where sno in
(select distinct(sno) from t_grade where cno in
(select cno from t_course where tno in
(select tno from t_teacher where tname = '李白')
)
);
--7、查询课程编号“c002”的成绩比课程编号“c001”课程低的所有同学的学号、姓名;
select g1.sno,(select sname from t_student where sno = g1.sno) as "姓名"
from t_grade g1,t_grade g2
where g1.sno = g2.sno
and g1.cno = 'c001'
and g2.cno = 'c002'
and g1.grade >=g2.grade;
--8、查询所有课程成绩小于60 分的同学的学号、姓名;
select sno,sname from t_student where sno not in
(select distinct(sno) from t_grade where grade>=60);
--9、查询没有学全所有课的同学的学号、姓名;
insert into t_grade values('s001','c003',60);
insert into t_grade values('s001','c005',60);
select g.sno,(select sname from t_student where sno = g.sno) as "姓名"
from t_grade g
group by g.sno
having count(1) <
(select count(1) from t_course);
--选修课程数不等于课程总数的学生即为查询结果
--10、查询至少有一门课与学号为“s003”的同学所学相同的同学的学号和姓名;
select distinct(g.sno),(select sname from t_student where sno = g.sno) as "姓名"
from t_grade g where g.cno in
(select cno from t_grade where sno = 's003')
and g.sno <> 's003';
--11、查询至少学过学号为“s003”同学所有一门课的其他同学学号和姓名;
--这题目和上一题不是一样的??
--改一下:查询学过学号为“s003”同学所有课的其他同学学号和姓名;
select * from t_grade;
update t_grade set cno = 'c005' where grade = 65 and sno = 's004';
select s.sno,s.sname
from t_student s inner join t_grade g2
on (s.sno = g2.sno)
where g2.cno in
(select cno from t_grade g where g.sno = 's003')
group by s.sno,s.sname
having count(g2.cno) =
(select count(1) from t_grade g where g.sno = 's003')
and s.sno <> 's003';
--这个解决方案有点辣鸡,不知道有没有更好的办法
--12、把“成绩”表中“李白”老师教的课的成绩都更改为此课程的平均成绩;
select * from t_grade;
update t_grade g set g.grade=
(select avg(grade) from t_grade where cno=g.cno)
where g.cno in
(select c.cno from t_course c where c.tno in(
select t.tno from t_teacher t where t.tname='李白')
);
--13、查询和“s003”号的同学学习的课程完全相同的其他同学学号和姓名;
select s.sno,s.sname
from t_student s inner join t_grade g2
on (s.sno = g2.sno)
where g2.cno in
(select cno from t_grade g where g.sno = 's003')
group by s.sno,s.sname
having count(g2.cno) =
(select count(1) from t_grade g where g.sno = 's003')
and s.sno <> 's003'
and (select count(1) from t_grade g where g.sno = 's003') =
(select count(1) from t_grade g where g.sno = s.sno);
--和11题的主要区别就是,一个全学过,一个全相同,包含与相等的区别
--这里肯定有更好的解决方案,但是懒得去写了,有想法的可以留言给我
--14、查询各科成绩最高和最低的分:以如下形式显示:课程ID,最高分,最低分
select cno ,max(grade),min(grade) from t_grade group by cno;
--15、按各科平均成绩从低到高和及格率的百分数从高到低顺序
select * from t_grade;
update t_grade set grade = 65 where cno = 'c004' and sno = 's002';
select g.cno as 课程id,avg(g.grade) as 平均成绩,
100*sum(case when g.grade >=60 then 1 else 0 end)/count(1)||'%' as 及格率
from t_grade g
group by g.cno
order by avg(g.grade),
sum(case when g.grade>=60 then 1 else 0 end)/count(1) desc;
--16、查询不同老师所教不同课程平均分从高到低显示
select max(t.tno) as "教师id",max(t.tname) as "教师姓名",
max(c.cno) as "课程id",max(c.cname) as "课程名称",avg(g.grade) as "平均成绩"
from t_grade g,t_course c,t_teacher t
where c.cno=g.cno and c.tno = t.tno
group by c.cno
order by avg(g.grade) desc;
--17、统计列印各科成绩,各分数段人数:课程ID,课程名称,[100-85],[85-70],[70-60],[ <60]
select c.cno,c.cname,
(case when g.grade >=85 then '[100-85]'
when g.grade >=70 and g.grade <85 then '(85-70]'
when g.grade >=70 and g.grade <85 then '(70-60]'
else '<60'
end) as fd,
count(1)
from t_grade g,t_course c
where g.cno = c.cno
group by c.cno ,c.cname,
(case when g.grade >=85 then '[100-85]'
when g.grade >=70 and g.grade <85 then '(85-70]'
when g.grade >=70 and g.grade <85 then '(70-60]'
else '<60'
end)
order by c.cno,c.cname,fd;
rollback; --出现了误操作
commit; --存档
--18、查询各科成绩前2名的记录:(不考虑成绩并列情况)
select * from t_grade;
select sno,cno,grade from t_grade g1 where grade in
(select grade from t_grade g2
where g2.cno=g1.cno and rownum<=2)
order by g1.cno,g1.grade desc
--19、查询每门课程被选修的学生数
select cno,count(cno) from t_grade group by cno;
--20、查询出只选修了一门课程的全部学生的学号和姓名
select g.sno,(select sname from t_student where sno = g.sno) as "姓名"
from t_grade g group by sno having count(sno) = 1;
--21、查询同名同性学生名单,并统计同名人数
insert into t_student values('s006','公孙离','男',29);
commit;
select * from t_student;
select sname,count(sname) as "人数" from t_student group by sname
having count(sname)>1;
--22、2001 年出生的学生名单(注:Student 表中Sage 列的类型是number)
select sno,sname,age,sex
from t_student
where age=
floor(months_between(sysdate,to_date('2001-01-01','yyyy-mm-dd'))/12);
--23、查询每门课程的平均成绩,结果按平均成绩升序排列,平均成绩相同时,按课程号降序排列
select cno,avg(grade) from t_grade
group by cno
order by avg(grade) desc;
--24、查询平均成绩大于85 的所有学生的学号、姓名和平均成绩
select s.sno,s.sname,t.gr from t_student s right join
(select sno,avg(grade) as gr from t_grade group by sno having avg(grade)>65) t
on s.sno = t.sno
order by t.gr desc;
--25、查询课程名称为“打野教学”,且分数低于60 的学生姓名和分数
select g.sno,(select sname from t_student where sno = g.sno) as "姓名" ,
g.grade from t_grade g where g.cno =
(select cno from t_course where cname = '打野教学')
and g.grade < 60;
--26、查询所有学生的选课情况;
select s.sno,s.sname,g.cno,(select cname from t_course where cno = g.cno) as "课程名"
from t_student s left join t_grade g
on s.sno = g.sno;
--27、查询任何一门课程成绩在70 分以上的姓名、课程名称和分数;
select g.sno,(select sname from t_student where sno = g.sno) as "姓名" ,
g.cno,(select cname from t_course where cno = g.cno) as "课程名",
grade
from t_grade g where grade > 70;
--28、查询不及格的课程,并按课程号从大到小排列
select cno,sno from t_grade g where g.grade < 60 order by cno;
--29、查询课程编号为c001 且课程成绩在80 分以上的学生的学号和姓名;
select sno,(select sname from t_student where sno = g.sno) as "姓名"
from t_grade g where cno = 'c001' and grade >=80;
--30、查询选修“李白”老师所授课程的学生中,成绩最高的学生姓名及其成绩
select cno,sno,grade from t_grade where cno in
(select c.cno from t_course c where c.tno in
(select t.tno from t_teacher t where t.tname='李白')
)
order by cno ,grade desc;
--这题不会,看了下别人的思路,分组找最高的分数,
--再看谁对应这个分数,可以实现,但我总感觉这里违背客观事实
--31、查询各个课程及相应的选修人数
select g.cno,(select cname from t_course where cno = g.cno) as "课程名",
count(1) from t_grade g group by cno order by cno;
--32、查询不同课程成绩相同的学生的学号、课程号、学生成绩
select g1.*,g2.* from t_grade g1,t_grade g2
where g2.grade = g1.grade and g1.cno <> g2.cno ;
--33、查询每门功课成绩最好的前两名
SELECT g1.* FROM t_grade g1 WHERE
(SELECT COUNT(1) FROM t_grade g2 WHERE
g1.cno=g2.cno AND g2.grade>=g1.grade)<=2
ORDER BY g1.cno,g1.grade DESC;
--34、统计每门课程的学生选修人数(超过2 人的课程才统计)。
--要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
select cno,count(1) from t_grade
group by cno
having count(1) >=2
order by count(1) desc,cno;
--35、检索至少选修两门课程的学生学号
select sno,count(1) from t_grade
group by sno
having count(1) >=2
--36、查询全部学生都选修的课程的课程号和课程名
--数据不支持,改成只差三个同学没选修的课程
select cno,count(1) from t_grade group by cno
having count(1) >=
((select count(1) from t_student)- 3);
--37、查询没学过“李白”老师讲授的任一门课程的学生姓名
select sno,(select sname from t_student where sno = g.sno) as "姓名"
from t_grade g where cno not in
(select c.cno from t_course c where c.tno in
(select t.tno from t_teacher t where t.tname='李白')
);
--38、查询两门以上不及格课程的同学的学号及其平均成绩
select sno,count(cno) from t_grade
where grade < 60
group by sno
having count(cno) >= 2;
--39、检索“c004”课程分数小于60,按分数降序排列的同学学号
insert into t_grade values('s002','c004',55);
insert into t_grade values('s003','c004',59);
commit;
select sno,grade from t_grade where cno = 'c004' and grade < 60;