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;

 

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