oracle基础查询练习题整理

以下是本次练习题需要用到的表和数据:
create table student(
sno varchar2(10) primary key,
sname varchar2(20),
sage number(2),
ssex varchar2(5)
);
create table teacher(
tno varchar2(10) primary key,
tname varchar2(20)
);
create table course(
cno varchar2(10),
cname varchar2(20),
tno varchar2(20),
constraint pk_course primary key (cno,tno)
);
create table sc(
sno varchar2(10),
cno varchar2(10),
score number(4,2),
constraint pk_sc primary key (sno,cno)
);
/*初始化学生表的数据**/
insert into student values (‘s001’,’张三’,23,’男’);
insert into student values (‘s002’,’李四’,23,’男’);
insert into student values (‘s003’,’吴鹏’,25,’男’);
insert into student values (‘s004’,’琴沁’,20,’女’);
insert into student values (‘s005’,’王丽’,20,’女’);
insert into student values (‘s006’,’李波’,21,’男’);
insert into student values (‘s007’,’刘玉’,21,’男’);
insert into student values (‘s008’,’萧蓉’,21,’女’);
insert into student values (‘s009’,’陈萧晓’,23,’女’);
insert into student values (‘s010’,’陈美’,22,’女’);
commit;
/********初始化教师表*************/
insert into teacher values (‘t001’, ‘刘阳’);
insert into teacher values (‘t002’, ‘谌燕’);
insert into teacher values (‘t003’, ‘胡明星’);
commit;
/*****初始化课程表******************/
insert into course values (‘c001’,’J2SE’,’t002’);
insert into course values (‘c002’,’Java Web’,’t002’);
insert into course values (‘c003’,’SSH’,’t001’);
insert into course values (‘c004’,’Oracle’,’t001’);
insert into course values (‘c005’,’SQL SERVER 2005’,’t003’);
insert into course values (‘c006’,’C#’,’t003’);
insert into course values (‘c007’,’JavaScript’,’t002’);
insert into course values (‘c008’,’DIV+CSS’,’t001’);
insert into course values (‘c009’,’PHP’,’t003’);
insert into course values (‘c010’,’EJB3.0’,’t002’);
commit;
/*****初始化成绩表*************/
insert into sc values (‘s001’,’c001’,78.9);
insert into sc values (‘s002’,’c001’,80.9);
insert into sc values (‘s003’,’c001’,81.9);
insert into sc values (‘s004’,’c001’,60.9);
insert into sc values (‘s001’,’c002’,82.9);
insert into sc values (‘s002’,’c002’,72.9);
insert into sc values (‘s003’,’c002’,81.9);
insert into sc values (‘s001’,’c003’,’59’);
commit;

1、查询“c001”课程比“c002”课程成绩高的所有学生的学号

--c001比c002成绩高应该是同一个人进行比较,可以先查询c001的再进行同一个人关联比较
SELECT r.sNo FROM sc r 
WHERE r.cNo = 'c001'
AND EXISTS
(
  SELECT 1 FROM sc s WHERE s.cNo = 'c002' AND s.sNo = r.sNo AND r.score > s.score
)

2、查询平均成绩大于60 分的同学的学号和平均成绩;

--根据学生学号进行分组求每个人的平均成绩
SELECT r.sNo,AVG(r.score) FROM sc r 
GROUP BY r.sNo 
HAVING AVG(r.score) > 60

3、查询所有同学的学号、姓名、选课数、总成绩;

--查询所有学生,说明查询主表是student
SELECT r.sNo,r.sName,COUNT(s.sNo),SUM(NVL(s.score,0)) FROM student r 
LEFT JOIN 
sc s ON s.sNo = r.sNo 
GROUP BY r.sNo,r.sName
ORDER BY r.sNo

4、查询姓“刘”的老师的个数;

--说明老师名称是以‘刘’开头的
SELECT COUNT(*) FROM teacher r 
WHERE r.tName LIKE '刘%'

5、查询没学过“谌燕”老师课的同学的学号、姓名;

--首先查出谌燕老师所教授的课程编号,然后查出学过的学生编号然后排除即可
SELECT sNo,sName FROM student WHERE sNo NOT IN 
(
  SELECT DISTINCT r.sNo FROM sc r 
  INNER JOIN 
  course s ON s.cNo = r.cNo 
  INNER JOIN 
  teacher t ON t.tNo = s.tNo 
  WHERE t.tName = '谌燕'
)

6、查询学过“c001”并且也学过编号“c002”课程的同学的学号、姓名;

--c001和c002两门课程都学过,需要确保是同一个人。可以使用EXISTS关联
SELECT r.sNo,s.sName FROM sc r 
LEFT JOIN 
student s ON s.sNo = r.sNo 
WHERE r.cNo = 'c001'
AND EXISTS
(
  SELECT 1 FROM sc s WHERE s.cNo = 'c002' 
  AND s.sNo = r.sNo 
)

7、查询学过“谌燕”老师所教的所有课的同学的学号、姓名;

--谌燕老师所教授的所有课程编号,然后根据学号进行分组
SELECT t.sNo,u.sName,COUNT(*) FROM sc t
LEFT JOIN 
student u ON u.sNo = t.sNo 
WHERE t.cNo IN 
(
  SELECT r.cNo FROM course r 
  INNER JOIN 
  teacher s ON s.tNo = r.tNo 
  WHERE s.tName = '谌燕'
) 
GROUP BY t.sNo,u.sName
HAVING COUNT(*) = 
(
  SELECT COUNT(r.cNo) FROM course r
  INNER JOIN 
  teacher s ON s.tNo = r.tNo 
  WHERE s.tName = '谌燕'
)

8、查询课程编号“c002”的成绩比课程编号“c001”课程低的所有同学的学号、姓名;

--这里比较的是同一个人的两门成绩,关键点在于同一个人
SELECT r.sNo,s.sName FROM sc r 
LEFT JOIN 
student s ON s.sNo = r.sNo
WHERE r.cNo = 'c002' AND EXISTS
(
  SELECT 1 FROM sc s WHERE s.cNo = 'c001' AND s.sNo = r.sNo AND r.score < s.score
)

9、查询所有课程成绩小于60 分的同学的学号、姓名;

--这题由歧义,目前按照分数小于60分进行条件限制
SELECT DISTINCT r.sNo,s.sName FROM sc r 
LEFT JOIN 
student s ON s.sNo = r.sNo 
WHERE r.score < 60

10、查询没有学全所有课的同学的学号、姓名;

--其实这题有一种巧妙的方法,如果学全了全部课程则说明每个人的学习课程数等于总课程数
SELECT r.sNo,s.sName FROM sc r 
LEFT JOIN 
student s ON s.sNo = r.sNo
GROUP BY r.sNo,s.sName 
HAVING COUNT(*) = 
(
  SELECT COUNT(*) FROM course 
)

11、查询至少有一门课与学号为“s001”的同学所学相同的同学的学号和姓名;

--首先求出s001所学的课程代码
SELECT DISTINCT s.sNo,t.sName FROM sc s 
LEFT JOIN 
student t ON t.sNo = s.sNo
WHERE s.cNo IN 
(
  SELECT r.cNo FROM sc r 
  WHERE r.sNo = 's001'
)
AND s.sNo != 's001'

12、查询至少学过学号为“s001”同学所学课程任意一门课的其他同学学号和姓名;

--这题和上面至少有一门课程相同的类似
SELECT DISTINCT s.sNo,t.sName FROM sc s 
LEFT JOIN 
student t ON t.sNo = s.sNo 
WHERE s.cNo IN 
(
  SELECT r.cNo FROM sc r 
  WHERE r.sNo = 's001'
)
AND s.sNo != 's001'

13、把“SC”表中“谌燕”老师教的课的成绩都更改为此课程的平均成绩;

--首先复制一张sc表
--CREATE TABLE sc1 AS SELECT * FROM sc 
--求出谌燕老师所教授课程的平均成绩,应该是根据课程编号进行分组求平均值
--因为是将课程改为对应课程的平均成绩
UPDATE sc1 u SET u.score = 
(
  SELECT avg_score FROM 
  (
    SELECT r.cNo,ROUND(AVG(r.score),2) avg_score FROM sc1 r 
    INNER JOIN 
    course s ON s.cNo = r.cNo 
    INNER JOIN 
    teacher t ON t.tNo = s.tNo 
    WHERE t.tName = '谌燕'
    GROUP BY r.cNo 
  ) v WHERE v.cNo = u.cNo
)

14、查询和“s001”号的同学学习的课程完全相同的其他同学学号和姓名;

--查询所学课程完全相同,说明课程一样,数量一样两个条件
--数量一样可以根据学号进行分组对结果进行比较
SELECT r.sNo,COUNT(*) FROM sc r 
WHERE r.cNo IN 
(
  SELECT cNo FROM sc WHERE sNo = 's001'
)
AND r.sNo != 's001'
GROUP BY r.sNo
HAVING COUNT(*) = 
(
  SELECT COUNT(*) FROM sc WHERE sNo = 's001'
)

15、删除学习“谌燕”老师课的SC 表记录;

--首先复制一张表
--CREATE TABLE sc2 AS SELECT * FROM sc 
--查出谌燕老师所教授的课程代码
DELETE FROM sc2 WHERE cNo IN 
(
  SELECT cNo FROM course r 
  INNER JOIN 
  teacher s ON s.tNo = r.tNo
  WHERE s.tName = '谌燕'
)

16、向SC 表中插入一些记录,这些记录要求符合以下条件:没有上过编号“c002”课程的同学学号、“c002”号课的平均成绩;

--复制一张表
--CREATE TABLE sc3 AS SELECT * FROM sc 
--查出上过c002课程编号的学生代码,然后排除
INSERT INTO sc
SELECT r.sNo,'c002',
(SELECT ROUND(AVG(score),2) FROM sc WHERE cNo = 'c002' GROUP BY cNo) 
FROM student r 
WHERE r.sNo NOT IN 
(
  SELECT sNo FROM sc 
  WHERE cNo = 'c002'
)

17、查询各科成绩最高和最低的分:以如下形式显示:课程ID,最高分,最低分

--根据课程编号进行分组
SELECT r.cNo,MAX(r.score),MIN(r.score) FROM sc r 
GROUP BY r.cNo
18、按各科平均成绩从低到高和及格率的百分数从高到低顺序
--这题的关键就是求及格率,仍然是根据课程编号进行分组
SELECT r.cNo,AVG(r.score)
,SUM(CASE WHEN r.score >= 60 THEN 1 ELSE 0 END)/COUNT(*) * 100 || '%'
FROM sc r
GROUP BY r.cNo
ORDER BY AVG(r.score) ASC
                   ,SUM(CASE WHEN r.score >= 60 THEN 1 ELSE 0 END)/COUNT(*) DESC    

19、查询不同老师所教不同课程平均分从高到低显示

--不同老师,不同课程。根据这两个参数进行分组求平均值
SELECT s.tNo,r.cNo,ROUND(AVG(r.score),2) FROM sc r 
INNER JOIN 
course s ON s.cNo = r.cNo
GROUP BY s.tNo,r.cNo

20、统计列印各科成绩,各分数段人数:课程ID,课程名称,[100-85],[85-70],[70-60],[ <60]

--根据课程分组,使用sum + case when
SELECT r.cNo,s.cName
,SUM(CASE WHEN r.score > 85 AND r.score <= 100 THEN 1 ELSE 0 END) A
,SUM(CASE WHEN r.score > 70 AND r.score <= 85 THEN 1 ELSE 0 END) B
,SUM(CASE WHEN r.score > 60 AND r.score <= 70 THEN 1 ELSE 0 END) C
,SUM(CASE WHEN r.score <= 60 THEN 1 ELSE 0 END) D
FROM sc r
LEFT JOIN 
course s ON s.cNo = r.cNo 
GROUP BY r.cNo,s.cName
ORDER BY r.cNo

21、查询各科成绩前三名的记录:(不考虑成绩并列情况)

--首先是不同课程然后又要求出前三名
--这里使用ROW_NUMBER() OVER()
SELECT cNo,sNo,score,pm FROM
(
  SELECT r.cNo,r.sNo,r.score,
  ROW_NUMBER() OVER (PARTITION BY r.cNo ORDER BY r.score DESC) pm
  FROM sc r
) WHERE pm <= 3

22、查询每门课程被选修的学生数

--这里的查询主表应该是course
SELECT r.cnO,count(s.cNo) FROM course r 
LEFT JOIN 
sc s ON s.cNo = r.cNo
GROUP BY r.cNo

23、查询出只选修了一门课程的全部学生的学号和姓名

--根据学生学号分组,选课数为1即可
SELECT r.sNo,s.sName,COUNT(*) FROM sc r 
LEFT JOIN 
student s ON s.sNo = r.sNo
GROUP BY r.sNo,s.sName
HAVING COUNT(*) = 1

24、查询男生、女生人数

--查询学生表,根据性别进行分组
SELECT r.sSex,count(*) FROM student r 
GROUP BY r.sSex

25、查询姓“张”的学生名单

--说明名字是‘张’开头的
SELECT * FROM student r 
WHERE r.sName LIKE '张%'

27、1981 年出生的学生名单(注:Student 表中Sage 列的类型是number)

--1981年出生说明当前系统时间减去1981等于学生的年龄
SELECT * FROM student r 
WHERE r.sAge = TO_NUMBER(TO_CHAR(SYSDATE,'yyyy')) - 1981

28、查询每门课程的平均成绩,结果按平均成绩升序排列,平均成绩相同时,按课程号降序排列

--根据课程编号进行分组,求出平均成绩
SELECT r.cNo,ROUND(AVG(r.score),2) FROM sc r 
GROUP BY r.cNo 
ORDER BY AVG(r.score) ASC,r.cNo DESC 

29、查询平均成绩大于85 的所有学生的学号、姓名和平均成绩

--根据学生编号进行分组,求出每个学生的平均成绩
SELECT r.sNo,s.sName,AVG(r.score) FROM sc r 
LEFT JOIN 
student s ON s.sNo = r.sNo
GROUP BY r.sNo,s.sName

30、查询课程名称为“数据库”,且分数低于60 的学生姓名和分数

--两个条件:一个数据库,一个分数低于60分
SELECT r.sNo,t.sName,r.score FROM sc r 
INNER JOIN 
course s ON s.cNo = r.cNo 
INNER JOIN 
student t ON t.sNo = r.sNo
WHERE s.cName = '数据库' AND r.score < 60

31、查询所有学生的选课情况;

--既然是查询所有,则查询主表是student
SELECT r.sNo,r.sName,NVL(t.cName,'未选课') FROM student r 
LEFT JOIN 
sc s ON s.sNo = r.sNo 
LEFT JOIN 
course t ON t.cNo = s.cNo 

32、查询任何一门课程成绩在70 分以上的姓名、课程名称和分数;

SELECT s.sName,t.cName,r.score FROM sc r 
LEFT JOIN 
student s ON s.sNo = r.sNo
LEFT JOIN 
course t ON t.cNo = r.cNo 
WHERE r.score >= 70

33、查询不及格的课程,并按课程号从大到小排列

SELECT r.cNo,s.cName,r.score FROM sc r 
LEFT JOIN 
course s on s.cNo = r.cNo
WHERE r.score < 60
ORDER BY r.cNo

34、查询课程编号为c001 且课程成绩在80 分以上的学生的学号和姓名;

--两个条件:课程号和成绩
SELECT r.sNo,s.sName FROM sc r 
LEFT JOIN 
student s ON s.sNo = r.sNo
WHERE r.cNo = 'c001' AND r.score > 80

35、求选了课程的学生人数

--选了课程的学生肯定在sc表中
SELECT COUNT(DISTINCT sNo) from sc 

36、查询选修“谌燕”老师所授课程的学生中,成绩最高的学生姓名及其成绩

--其实可以理解为:sc表中课程是谌燕教授,然后求出其中最高分(每门课程的最高分)
SELECT x.sName,u.score FROM sc u 
LEFT JOIN 
student x ON x.sNo = u.sNo
WHERE EXISTS
(
  SELECT 1 FROM 
  (
    SELECT r.cNo,MAX(r.score) max_score FROM sc r 
    INNER JOIN 
    course s ON s.cNo = r.cNo 
    INNER JOIN 
    teacher t ON t.tNo = s.tNo 
    WHERE t.tName = '谌燕'
    GROUP BY r.cNo
  ) v WHERE v.cNo = u.cNo AND v.max_score = u.score
)

37、查询各个课程及相应的选修人数

--检索主表为course
SELECT r.cNo,COUNT(s.cNo) FROM course r 
LEFT JOIN 
sc s ON s.cNo = r.cNo
GROUP BY r.cNo

38、查询不同课程成绩相同的学生的学号、课程号、学生成绩

--都在sc表中检索,三个条件: 同一个人,课程不同,成绩相同
SELECT * FROM sc r 
WHERE EXISTS
(
  SELECT 1 FROM sc s 
  WHERE s.sNo = r.sNo AND s.cNo != r.cNo AND s.score = r.score
)

39、查询每门功课成绩最好的前两名

--这题依旧是使用分组求排名的方式
SELECT * FROM 
(
  SELECT r.cNo,r.sNo,r.score,
  ROW_NUMBER() OVER (PARTITION BY r.cNo ORDER BY r.score DESC) pm
  FROM sc r 
) WHERE pm <= 2

40、统计每门课程的学生选修人数(超过10 人的课程才统计)。要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列

--检索主表为course表
SELECT r.cNo,COUNT(s.cNo) FROM course r 
LEFT JOIN 
sc s ON s.cNo = r.cNo
GROUP BY r.cNo
HAVING COUNT(s.cNo) >= 10
ORDER BY COUNT(s.cNo) DESC,r.cNo ASC

41、检索至少选修两门课程的学生学号

--根据学生编号进行分组
SELECT sNo,COUNT(*) FROM sc
GROUP BY sNo
HAVING COUNT(*) >= 2

42、查询全部学生都选修的课程的课程号和课程名

--全部学生都选修,说明每门课人数等于总学生人数
SELECT r.cNo,s.cName,COUNT(*) FROM sc r 
LEFT JOIN 
course s ON s.cNo = r.cNo 
GROUP BY r.cNo,s.cName
HAVING COUNT(*) = 
(
  SELECT COUNT(*) FROM student 
)

43、查询没学过“谌燕”老师讲授的任一门课程的学生姓名

--首先查出学过谌燕老师课程的学生然后排除即可
SELECT u.sName FROM student u WHERE u.sNo NOT IN 
(
  SELECT DISTINCT r.sNo FROM sc r 
  INNER JOIN 
  course s ON s.cNo = r.cNo 
  INNER JOIN 
  teacher t ON t.tNo = s.tNo 
  WHERE t.tName = '谌燕'
)

44、查询两门以上不及格课程的同学的学号及其平均成绩

--根据学号进行分组,限制条件为分数大于等于2
SELECT r.sNo,AVG(r.score) FROM sc r 
WHERE r.score < 60
GROUP BY r.sNo
HAVING COUNT(*) >= 2

45、检索“c004”课程分数小于60,按分数降序排列的同学学号

SELECT r.sNo FROM sc r 
WHERE r.cNo = 'c004' AND r.score < 60

猜你喜欢

转载自blog.csdn.net/Mattscl/article/details/81437019