目录
一、前言
SQL简介
SQL 分类
二、实践(40道SQL题)
SQL是我接触的第二门编程语言,学得挺早,但到现在已经好几年没用过SQL了,因为搞机器学习用python(numpy/pandas),最近刷笔试题遇到SQL题都有点忘了,故再次拾起,回顾回顾。本文所使用的数据库为Oracle19c。
SQL (Structured Query Language) 是具有数据操纵和数据定义等多种功能的数据库语言,这种语言具有交互性特点,能为用户提供极大的便利,数据库管理系统应充分利用SQL语言提高计算机应用系统的工作质量与效率。
首先,建表,插入数据,以供后面的数据查询操作。
create table Student(sid varchar(10),sname varchar(10),sage varchar(10),ssex varchar(10)); insert into Student values('01' , '赵雷' , '1990-01-01' , '男'); insert into Student values('02' , '钱电' , '1990-12-21' , '男'); insert into Student values('03' , '孙风' , '1990-05-20' , '男'); insert into Student values('04' , '李云' , '1990-08-06' , '男'); insert into Student values('05' , '周梅' , '1991-12-01' , '女'); insert into Student values('06' , '吴兰' , '1992-03-01' , '女'); insert into Student values('07' , '郑竹' , '1989-07-01' , '女'); insert into Student values('08' , '王菊' , '1990-01-20' , '女'); create table Course(cid varchar(10),cname varchar(10),tid varchar(10)); insert into Course values('01' , '语文' , '02'); insert into Course values('02' , '数学' , '01'); insert into Course values('03' , '英语' , '03'); create table Teacher(tid varchar(10),tname varchar(10)); insert into Teacher values('01' , '张三'); insert into Teacher values('02' , '李四'); insert into Teacher values('03' , '王五'); create table SC(sid varchar(10),cid varchar(10),score number(18,1)); insert into SC values('01' , '01' , 80); insert into SC values('01' , '02' , 90); insert into SC values('01' , '03' , 99); insert into SC values('02' , '01' , 70); insert into SC values('02' , '02' , 60); insert into SC values('02' , '03' , 80); insert into SC values('03' , '01' , 80); insert into SC values('03' , '02' , 80); insert into SC values('03' , '03' , 80); insert into SC values('04' , '01' , 50); insert into SC values('04' , '02' , 30); insert into SC values('04' , '03' , 20); insert into SC values('05' , '01' , 76); insert into SC values('05' , '02' , 87); insert into SC values('06' , '01' , 31); insert into SC values('06' , '03' , 34); insert into SC values('07' , '02' , 89); insert into SC values('07' , '03' , 98);
两张表的数据如下:
select distinct t1.sid as sid from (select * from sc where cid='01')t1 left join (select * from sc where cid='02')t2 on t1.sid=t2.sid where t1.score>t2.score;
2、查询平均成绩大于60分的同学的学号和平均成绩;
select sid ,avg(score) from sc group by sid having avg(score)>60;
3、查询所有同学的学号、姓名、选课数、总成绩
select student.sid as sid ,sname ,count(distinct cid) course_cnt ,sum(score) as total_score from student left join sc on student.sid=sc.sid group by student.sid,sname;
4、查询姓“李”的老师的个数;
select count(distinct tid) as teacher_cnt from teacher where tname like '李%';
5、查询没学过“张三”老师课的同学的学号、姓名;
select sid,sname from student where sid not in ( select s.sid from sc s where cid in ( select c.cid from course c inner join teacher t on c.tid=t.tid where t.tname='张三' ));
6、查询学过“01”并且也学过编号“02”课程的同学的学号、姓名;
select sid,sname from student where sid in ( select sid from sc s1 where s1.cid = '01' and exists (select 1 from sc s2 where s2.cid = '02' and s1.sid = s2.sid) );
7、查询学过“张三”老师所教的课的同学的学号、姓名
select sid,sname from student where sid in ( select sid from sc s inner join course c on s.cid=c.cid inner join teacher t on c.tid = t.tid where t.tname='张三' );
8、查询课程编号“01”的成绩比课程编号“02”课程低的所有同学的学号、姓名;
select sid,sname from student where sid in( select sid from sc s1 where s1.cid='01' and exists (select 1 from sc s2 where s1.sid=s2.sid and s2.cid='02' and s1.score9、查询所有课程成绩小于60分的同学的学号、姓名;
--方法一:找分数表中分数大于60分的同学,排除这些人即可 select sid,sname from student where sid not in( select sid from sc where score>=60) and sid in (select sid from sc); --方法二:分组 SELECT s.sid,s.sname FROM student s inner join ( select sid from sc group by sid having max(score) < 60 ) t on s.sid = t.sid10、查询没有学全所有课的同学的学号、姓名;
select sid,sname from student where sid not in( select sid from sc group by sid having count(distinct cid)=(select count(distinct cid) from course));11、查询至少有一门课与学号为“01”的同学所学相同的同学的学号和姓名;
select sid,sname from student where sid in( select distinct sid from sc s1 where sid !='01' and exists (select 1 from sc s2 where sid ='01' and s1.cid=s2.cid) );12、查询和"01"号的同学学习的课程完全相同的其他同学的学号和姓名
select sid,sname from student where sid in ( select s.sid from sc s inner join (select cid from sc where sid='01') x on s.cid=x.cid group by s.sid having count(s.cid)=(select count(cid) from sc where sid='01') ) and sid!='01' and sid in ( select sid from sc group by sid having count(*)=(select count(cid) from sc where sid='01') ) ;13、把“SC”表中“张三”老师教的课的成绩都更改为此课程的平均成绩;
update sc set score= ( select avg_score from ( select avg(score) avg_score from sc s inner join course c on s.cid = c.cid inner join teacher t on c.tid = t.tid where t.tname = '张三' ) x ) where cid in( select distinct s.cid from sc s inner join course c on s.cid = c.cid inner join teacher t on c.tid = t.tid where t.tname = '张三' );14、查询没学过"张三"老师讲授的任一门课程的学生姓名
select sid,sname from student where sid not in ( select sid from sc s inner join course c on s.cid=c.cid inner join teacher t on c.tid=t.tid where t.tname='张三');15、查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
select t.sid,t.sname,s.avg_score from student t inner join ( select sid,avg(score) avg_score from sc where score<60 group by sid having count(distinct cid)>=2 ) s on t.sid=s.sid;16、检索"01"课程分数小于60,按分数降序排列的学生信息
select t.sid,t.sname,s.score from sc s inner join student t on s.sid=t.sid where s.cid='01' and s.score<60 order by score desc17、按平均成绩从高到低显示所有学生的平均成绩
select t.sid,t.sname,s.avg_score from student t inner join (select sid,avg(score) avg_score from sc group by sid ) s on t.sid=s.sid order by avg_score desc;18、查询各科成绩最高分、最低分和平均分:以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率
select c.cid,c.cname,max(s.score) max_score,min(s.score) min_score,avg(s.score) avg_score, sum(case when score>=60 then 1 end)/count(1) pass_ratio from sc s inner join course c on s.cid=c.cid group by c.cid,c.cname;19、按各科平均成绩从低到高和及格率的百分数从高到低顺序
select cid,avg(score) avg_score, sum(case when score>=60 then 1 end)/count(1) pass_ratio from sc group by cid order by avg_score,pass_ratio desc;20、查询学生的总成绩并进行排名
select sid,sum(score) sum_score , rank() over(order by sum(score) desc) rank from sc group by sid;21、查询不同老师所教不同课程平均分从高到低显示
select t.tname,c.cname,avg(s.score) avg_score from course c inner join teacher t on c.tid = t.tid inner join sc s on c.cid=s.cid group by t.tname,c.cname order by avg_score desc;22、查询所有课程的成绩第2名到第3名的学生信息及该课程成绩
select sid,cid,score,r from ( select s.*,dense_rank() over(partition by cid order by score desc) r from sc s ) m where r=2 or r=3;23、统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[0-60]及所占百分比
select c.cid,c.cname, sum(case when s.score>=85 then 1 else 0 end) between85to100, sum(case when s.score>=85 then 1 else 0 end)/count(1) between85to100_ratio, sum(case when s.score>=70 and s.score<85 then 1 else 0 end) between70to85, sum(case when s.score>=70 and s.score<85 then 1 else 0 end)/count(1) between70to85_ratio, sum(case when (s.score>=60 and s.score<70) then 1 else 0 end) between60to70, sum(case when (s.score>=60 and s.score<70) then 1 else 0 end)/count(1) between60to70_ratio, sum(case when (s.score<60) then 1 else 0 end) between0to60, sum(case when (s.score<60) then 1 else 0 end)/count(1) between0to60_ratio from sc s inner join course c on s.cid=c.cid group by c.cid,c.cname;24、查询学生平均成绩及其名次
select sid,avg(score) avg_score ,row_number() over (order by avg(score) desc) AS rank from sc group by sid;25、查询各科成绩前三名的记录
select cid,sid,score,rank from ( select s.*,rank() over (partition by cid order by score desc) rank from sc s ) t where t.rank<=3;26、查询每门课程被选修的学生数
select cid,count(distinct sid) cnt from sc group by cid;27、查询出只选修了两门课程的全部学生的学号和姓名
select s.sid,s.sname from sc left join student s on sc.sid = s.sid group by s.sid,s.sname having count(distinct cid)=2;28、查询男生、女生人数
--方法一 select sum(decode(ssex,'男',1,0)) AS 男生人数 ,sum(decode(ssex,'女',1,0)) AS 女生人数 from student; --方法二 select ssex,count(ssex) from student group by ssex;29、查询名字中含有"风"字的学生信息
select * from student where sname LIKE '%风%'30、查询同名同性学生名单,并统计同名人数
select sname ,count(sname) cnt from student group by sname having count(sname)>=2;31、查询1990年出生的学生名单
select * from student where substr(sage,1,4)='1990';32、查询每门课程的平均成绩,结果按平均成绩升序排列
select cid,avg(score) as avg_score from sc group by cid order by avg_score33、查询不及格的课程,并按课程号从大到小排列
select cid,sid,score from sc where score<60 order by cid desc,sid;34、查询课程编号为"01"且课程成绩在60分以上的学生的学号和姓名;
select sid,cid,score from sc where cid='01' and score>60;35、查询选修“张三”老师所授课程的学生中,成绩最高的学生姓名及其成绩
select * from ( select sc.sid,sname,cname,score from sc left join course on sc.cid=course.cid left join teacher on course.tid=teacher.tid left join student on sc.sid=student.sid where tname='张三' order by score desc ) m where rownum<=1; --以上SQL未考虑同分的情况,即最高分可能有多个人 --修改后: select sname,score from sc left join student on sc.sid=student.sid where score=( select max(score) as max_score from sc left join course on sc.cid=course.cid left join teacher on course.tid=teacher.tid where tname='张三' );36、统计每门课程的学生选修人数(超过5人的课程才统计)。要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
select cid ,count(sid) cnt from sc group by cid having count(sid)>=5 order by cnt desc,cid;37、检索至少选修两门课程的学生学号
select sid ,count(cid) from sc group by sid having count(cid)>=2;38、查询各学生的年龄
select (sysdate-to_date(sage,'yyyy-mm-dd'))/365 from student;39、查询本月过生日的学生
select * from student where to_date(sage,'yyyy-mm-dd')>=trunc(sysdate,'mm') and to_date(sage,'yyyy-mm-dd')40、查询年龄最大的学生
select * from ( select * from student order by sage ) t where rownum<=1;