Oracle入门--day3--子查询

今天,主要是题目

 

--建表
--学生表:学号、姓名、性别、年龄
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;

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章