SQL(之一)-SQL经典题目
Posted Cinderella_008
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL(之一)-SQL经典题目相关的知识,希望对你有一定的参考价值。
说明:以下SQL练习题(主要针对DBMS为ORACLE),题目来自网络,本人整理编辑完成,难度分为1-5星。
涉及的4个表的表间关系:
--0-查询每个学生、最高学科的成绩、及最高成绩的所在学科在班级中排名-★★★
--RANK() OVER(PARTITION BY XXX ORDER BY XXX ) 使用分析函数
SELECT A.SID,
A.CID,
A.SCORE,
DENSE_RANK() OVER(PARTITION BY A.CID ORDER BY A.SCORE DESC NULLS LAST) AS 学生最高分数所在该科目排名,
A.TOTAL_MAX_SCORE 当前科目最高分
FROM (SELECT T.SID,
T.CID,
T.SCORE,
MAX(T.SCORE) OVER(PARTITION BY T.SID) PRESON_MAX_SCORE, --个人最高分
MAX(T.SCORE) OVER(PARTITION BY T.CID) TOTAL_MAX_SCORE --当前科目最高分
FROM SC T) A
WHERE A.SCORE = A.PRESON_MAX_SCORE
ORDER BY 2;
--1、查询"001"课程比"002"课程成绩高的所有学生的学号-★
SELECT T1.SID ,T1.SCORE ,T2.SCORE FROM SC T1
LEFT JOIN SC T2 ON T1.SID=T2.SID
WHERE T1.CID='001' AND T2.CID='002' AND T1.SCORE >T2.SCORE ORDER BY 1;
--2、查询平均成绩大于60分的同学的学号和平均成绩-★
SELECT T1.SID ,ROUND(AVG(T1.SCORE),2) AVG_SCORE FROM SC T1
GROUP BY T1.SID HAVING AVG(T1.SCORE)>60 ORDER BY 2 DESC,1 ;
--3、查询所有同学的学号、姓名、选课数、总成绩-★
SELECT T1.SID ,T2.SNAME ,COUNT(T1.CID) COUNT_CID ,SUM(T1.SCORE)SUM_SCORE FROM SC T1
LEFT JOIN STUDENT T2 ON T1.SID=T2.SID
GROUP BY T1.SID ,T2.SNAME ORDER BY 1,4 DESC,3 ;
--4、查询姓"李"的老师的个数-★
SELECT COUNT (1) FROM TEACHER T1 WHERE T1.TNAME LIKE '李%';
--5A、查询没学过"叶平"老师课的同学的学号、姓名-★★
--5B、查询没学过"叶平"老师讲授的任一门课程的学生姓名-★★
--思路:反其道而行之,查询学过"叶平"老师 任意课程 的学生,然后排除这些学生
--方式1:
SELECT DISTINCT T4.SID,T4.SNAME FROM STUDENT T4 WHERE T4.SID NOT IN (
SELECT T3.SID FROM SC T3 WHERE T3.CID IN (
SELECT T2.CID FROM TEACHER T1 ,COURSE T2 WHERE T1.TID=T2.TID AND T1.TNAME ='叶平'
)) ORDER BY 1 ;
--方式2
SELECT DISTINCT T4.SID,T4.SNAME FROM STUDENT T4 WHERE T4.SID NOT IN (
SELECT DISTINCT T1.SID FROM SC T1 WHERE EXISTS
(SELECT * FROM COURSE T2, TEACHER T3 WHERE T3.TNAME='叶平' AND T1.CID=T2.CID AND T2.TID=T3.TID)
)ORDER BY 1;
--6、查询学过"001"并且也学过编号"002"课程的同学的学号、姓名-★
SELECT DISTINCT T1.SID ,T3.SNAME FROM SC T1
LEFT JOIN SC T2 ON T1.SID=T2.SID
LEFT JOIN STUDENT T3 ON T3.SID=T1.SID AND T3.SID=T2.SID
WHERE T1.CID='001' AND T2.CID='002'
ORDER BY 1 ;
--或者
SELECT T1.SID ,T3.SNAME FROM SC T1,SC T2 ,STUDENT T3 WHERE T1.CID='001'AND T2.CID='002' AND T1.SID=T2.SID
AND T1.SID=T3.SID
ORDER BY 1 ;
--7、查询学过"叶平"老师所教的所有课的同学的学号、姓名-★★
SELECT A.SID,B.SNAME FROM (
SELECT DISTINCT T1.SID,T1.CID FROM SC T1
WHERE T1.CID IN(SELECT T2.CID FROM TEACHER T1 ,COURSE T2 WHERE T1.TID=T2.TID AND T1.TNAME ='叶平')--查询出叶平老师所教课程的课程ID
)A --临时表
LEFT JOIN STUDENT B ON A.SID=B.SID GROUP BY A.SID,B.SNAME
HAVING COUNT(DISTINCT A.CID)>=
(SELECT COUNT(DISTINCT T2.CID ) FROM TEACHER T1 ,COURSE T2 WHERE T1.TID=T2.TID AND T1.TNAME ='叶平')--查询出叶平老师所教课程的课程数量
ORDER BY 1 ;
--8、查询课程编号"002"的成绩比课程编号"001"课程低的所有同学的学号、姓名-★
SELECT T1.SID , T3.SNAME ,T1.SCORE AS SC_002 ,T2.SCORE AS SC_001
FROM SC T1
LEFT JOIN SC T2 ON T1.SID=T2.SID
LEFT JOIN STUDENT T3 ON T1.SID=T3.SID AND T3.SID=T2.SID
WHERE T1.CID='002' AND T2.CID='001' AND T1.SCORE<T2.SCORE
ORDER BY 3 DESC,1 ;
--9、查询所有课程成绩小于60分的同学的学号、姓名-★
--思路:若最大的成绩小于60分,则该同学所有课程成绩必定都小于60分
SELECT S1.SID 学号, S1.SNAME 姓名
FROM STUDENT S1, SC S2
WHERE S1.SID = S2.SID
GROUP BY S1.SID, S1.SNAME HAVING MAX(S2.SCORE) < 60;
--10、查询没有学全所有课的同学的学号、姓名-★★
SELECT T1.SID, T2.SNAME ,COUNT(DISTINCT T1.CID) AS 学生选课数量
FROM SC T1,STUDENT T2
WHERE T1.SID=T2.SID
GROUP BY T1.SID,T2.SNAME
HAVING COUNT(DISTINCT T1.CID) <
(SELECT COUNT(DISTINCT T2.CID) AS SC_COUNT FROM COURSE T2)--总的课程数量。小于总的课程数量即为"没有学全所有课"
ORDER BY 1;
--11A、查询至少有一门课与学号为"1001"的同学所学相同的同学的学号和姓名-★
SELECT SID 学号, SNAME 姓名 FROM STUDENT WHERE SID IN
(SELECT DISTINCT SID FROM SC WHERE CID IN
(SELECT CID FROM SC WHERE SID='1001' --查出'1001'同学所学选的所有课程ID
)
) ORDER BY 1;
--11B、查询至少学过学号为"1001"同学所有一门课的其他同学学号和姓名-★
--与上题11A基本类似。区别:把1001同学排除掉,因为此题要求是"其他同学学号和姓名"
SELECT SID 学号, SNAME 姓名 FROM STUDENT WHERE SID IN
(SELECT DISTINCT SID FROM SC WHERE CID IN
(SELECT CID FROM SC WHERE SID='1001' --查出'1001'同学所学选的所有课程ID
)
) AND SID<> '1001' ORDER BY 1;
--12 、查询各科成绩最高和最低的分:以如下形式显示:课程ID ,最高分,最低分-★
SELECT T.CID 课程ID ,MAX(T.SCORE)最高分 ,MIN(T.SCORE) 最低分 FROM SC T GROUP BY T.CID ORDER BY 1 ;
--13、把"SC"表中"叶平"老师教的课的成绩都更改为此课程的平均成绩-★★★
--*推荐方法1:使用 MERGE INTO函数
MERGE INTO SC T1
USING (
SELECT T3.CID ,
AVG(T3.SCORE) AVG_SCORE
FROM SC T3 WHERE T3.CID IN (
SELECT T2.CID FROM COURSE T2 WHERE T2.TID IN(
SELECT T1.TID FROM TEACHER T1 WHERE T1.TNAME='叶平'))
GROUP BY T3.CID
) A --当成一个临时表A
ON (T1.CID=A.CID) --ON 条件要用括号
WHEN MATCHED THEN
UPDATE SET T1.SCORE=A.AVG_SCORE ;
--方法2 较为繁琐,但是思路清晰,容易理解
UPDATE SC T4
SET T4.SCORE=(
SELECT A.AVG_SCORE FROM
(
SELECT T3.CID ,
AVG(T3.SCORE) AVG_SCORE
FROM SC T3 WHERE T3.CID IN (
SELECT T2.CID FROM COURSE T2 WHERE T2.TID IN(
SELECT T1.TID FROM TEACHER T1 WHERE T1.TNAME='叶平'))
GROUP BY T3.CID --当成一个临时表A
) A WHERE A.CID=T4.CID )
WHERE T4.CID IN (SELECT B.CID FROM --要加限制条件,否则不匹配的学科 成绩会更新为NULL
(
SELECT T3.CID ,
AVG(T3.SCORE) AVG_SCORE
FROM SC T3 WHERE T3.CID IN (
SELECT T2.CID FROM COURSE T2 WHERE T2.TID IN(
SELECT T1.TID FROM TEACHER T1 WHERE T1.TNAME='叶平'))
GROUP BY T3.CID --当成一个临时表B 临时表A和临时表B完全一样 A=B
) B) ;
方法1
方法2
--14、查询和"1002"号的同学学习的课程完全相同的其他同学学号和姓名-★
SELECT T3.SID,T3.SNAME FROM STUDENT T3 WHERE T3.SID IN(
SELECT T2.SID FROM SC T2 WHERE T2.CID IN(SELECT CID FROM SC T1 WHERE T1.SID='1002') AND T2.SID<>'1002'
GROUP BY T2.SID
HAVING COUNT(DISTINCT T2.CID)=(SELECT COUNT(DISTINCT CID )FROM SC T1 WHERE T1.SID='1002')
) ORDER BY 1;
--15、删除学习"叶平"老师课的SC表记录-★
DELETE FROM SC T3 WHERE T3.CID IN(
SELECT T2.CID FROM COURSE T2 WHERE T2.TID IN(SELECT T1.TID FROM TEACHER T1 WHERE T1.TNAME='叶平')
);
--16、向SC表中插入一些记录,这些记录要求符合以下条件:①、没有上过编号"002"课程的同学学号 ②、插入"002"号课程的平均成绩-★★
--思路:首先查询没有上过002 课程的学生编码 使用MINUS 或者使用NOT IN
--方式1、使用 NOT IN
INSERT INTO SC
SELECT SID,'002',
(SELECT ROUND(AVG(SCORE),2) FROM SC WHERE CID='002')
FROM STUDENT WHERE SID NOT IN (SELECT SID FROM SC WHERE CID='002');
--方式2、使用MINUS
INSERT INTO SC
SELECT A.SID,B.CID,B.AVG_SOCRE FROM
(SELECT DISTINCT T2.SID FROM STUDENT T2
MINUS
SELECT DISTINCT T1.SID FROM SC T1 WHERE T1.CID='002' ) A ,
(SELECT T3.CID,ROUND(AVG(T3.SCORE),2) AVG_SOCRE FROM SC T3 WHERE CID='002' GROUP BY T3.CID)B ;
--17、按平均成绩从高到低显示所有学生的"数据库"、"企业管理"、"英语"三门的课程成绩,按如下形式显示:学生ID,数据库,企业管理,英语,有效课程数,有效平均分--★★
SELECT T1.SID 学生ID,
SUM(DECODE(T1.CID,NULL,0,1)) 企业管理,
SUM(DECODE(T2.CID,NULL,0,1)) 数据库,
SUM(DECODE(T3.CID,NULL,0,1)) 英语,
SUM(DECODE(T1.CID,NULL,0,1)+DECODE(T2.CID,NULL,0,1)+DECODE(T3.CID,NULL,0,1))有效课程数,
ROUND(SUM(NVL(T1.SCORE,0)+NVL(T2.SCORE,0)+NVL(T3.SCORE,0))/
(SUM(DECODE(T1.CID,NULL,0,1))+SUM(DECODE(T2.CID,NULL,0,1))+SUM(DECODE(T3.CID,NULL,0,1))),2) 有效平均分
FROM SC T1
LEFT JOIN (SELECT * FROM SC T WHERE T.CID='004' )T2 ON T1.SID=T2.SID
LEFT JOIN (SELECT * FROM SC T WHERE T.CID='006' )T3 ON T1.SID=T3.SID
WHERE T1.CID='001'
GROUP BY T1.SID
ORDER BY 1 ;
--18、查询各科成绩最高和最低的分:以如下形式显示:课程ID,课程名称,最高分,最低分-★
SELECT T.CID 课程ID ,T1.CNAME 课程名称, MAX(T.SCORE) 最高分 ,MIN(T.SCORE) 最低分 FROM SC T
LEFT JOIN COURSE T1 ON T1.CID=T.CID
GROUP BY T.CID,T1.CNAME ORDER BY 1;
--19、按各科平均成绩从低到高和及格率(60分及以上)的百分数从高到低顺序-★
SELECT T.CID ,ROUND(AVG(T.SCORE),2) AVG_SCORE,
TO_CHAR(ROUND((SUM(CASE WHEN T.SCORE>=60 THEN 1 ELSE 0 END )/COUNT(T.SID))*100,4),'990.99')||'%' PASS_PERCENT
FROM SC T GROUP BY T.CID ORDER BY 2,3;
--20、查询不同老师所教不同课程平均分从高到低显示-★
SELECT T3.TID,T3.TNAME,T1.CID,ROUND(AVG(T1.SCORE),2)AVG_SCORE FROM SC T1
LEFT JOIN COURSE T2 ON T1.CID=T2.CID
LEFT JOIN TEACHER T3 ON T2.TID=T3.TID
GROUP BY T3.TID,T3.TNAME,T1.CID ORDER BY 4 DESC ,1,3 ;
--21、查询各科成绩前三名的记录:(不考虑并列情况)-★★
重点:DENSE_RANK() OVER(PARTITION BY T.CID ORDER BY T.SCORE DESC NULLS LAST)
SELECT A.CID, A.SCORE, A.RANK
FROM (SELECT T.SID,
T.CID,
T.SCORE,
DENSE_RANK() OVER(PARTITION BY T.CID ORDER BY T.SCORE DESC NULLS LAST) AS RANK
FROM SC T --不考虑并列情况
) A
WHERE A.RANK <= 3;
--22、查询如下课程成绩第3名到第6名的学生成绩单:企业管理(001),马克思(002),UML (003),数据库(004),
按如下形式显示:[学生ID],[学生姓名],企业管理,马克思,UML,数据库,平均成绩-★★★★
SELECT C.SID 学生ID,
C.SNAME 学生姓名,
B.A001 企业管理,
B.A002 马克思,
B.A003 UML,
B.A004 数据库,
(NVL(B.A001,0)+NVL(B.A002,0)+NVL(B.A003,0)+NVL(B.A004,0))/4 平均成绩
FROM (--把以下查询结果看成 临时表B
WITH TEMP_RANK AS
(SELECT * FROM (
SELECT T.SID,T.CID,T.SCORE,
RANK() OVER(PARTITION BY T.CID ORDER BY T.SCORE DESC NULLS LAST ) RANK FROM SC T WHERE T.CID IN('001','002','003','004')
) A WHERE A.RANK BETWEEN 3 AND 6 )
SELECT * FROM TEMP_RANK B
PIVOT ( MAX(B.SCORE) FOR CID IN ( --注意CID 只能使用CID 不能使用表别名.CID,否则会报[ORA-01748:此处只允许简单的列名]错误
'001' AS A001,
'002' AS A002,
'003' AS A003,
'004' AS A004
))
) B LEFT JOIN STUDENT C ON B.SID=C.SID ;
--23、统计列印各科成绩,各分数段人数:课程ID,课程名称,A [100-85],B[85-70] ,C[70-60] ,D[<60]-★★
SELECT T1.CID,T2.CNAME ,
SUM (CASE WHEN T1.SCORE BETWEEN 85 AND 100 THEN 1 ELSE 0 END) A ,
SUM (CASE WHEN T1.SCORE BETWEEN 70 AND 84 THEN 1 ELSE 0 END) B ,
SUM (CASE WHEN T1.SCORE BETWEEN 60 AND 69 THEN 1 ELSE 0 END) C ,
SUM (CASE WHEN T1.SCORE <60 THEN 1 ELSE 0 END) D
FROM SC T1
LEFT JOIN COURSE T2 ON T1.CID=T2.CID
GROUP BY T1.CID,T2.CNAME
ORDER BY 1;
--24、查询学生平均成绩及其名次-★★
SELECT A.SID,
ROUND(A.AVG_SCORE, 2) AVG_SCORE,
RANK() OVER(ORDER BY A.AVG_SCORE DESC) AVG_RANK
FROM (SELECT T.SID, AVG(T.SCORE) AVG_SCORE FROM SC T GROUP BY T.SID) A
ORDER BY A.SID;
--25、查询各科成绩前三名的记录:(考虑成绩并列情况)-★★
--和21题类似。 重点:RANK() OVER(PARTITION BY T.CID ORDER BY T.SCORE DESC NULLS LAST)
SELECT A.CID, A.SCORE, A.RANK
FROM (SELECT T.SID,
T.CID,
T.SCORE,
RANK() OVER(PARTITION BY T.CID ORDER BY T.SCORE DESC NULLS LAST) AS RANK
FROM SC T --考虑并列情况
) A
WHERE A.RANK <= 3;
--26、查询每门课程被选修的学生数-★
SELECT T1.CID, T2.CNAME, COUNT(1) AS 选修数量
FROM SC T1
LEFT JOIN COURSE T2 ON T1.CID = T2.CID
GROUP BY T1.CID, T2.CNAME
ORDER BY 1;
--27、查询出只选修了一门课程的全部学生的学号和姓名-★
SELECT T1.SID, T2.SNAME, COUNT(DISTINCT T1.CID) AS 选课数量
FROM SC T1
LEFT JOIN STUDENT T2 ON T1.SID = T2.SID
GROUP BY T1.SID, T2.SNAME
HAVING COUNT(DISTINCT T1.CID) = 1;
--28、查询男生、女生人数-★
SELECT T.SSEX, COUNT(T.SID) FROM STUDENT T GROUP BY T.SSEX;
--29、查询姓"张"的学生名单-★
SELECT * FROM STUDENT T WHERE T.SNAME LIKE '张%';
--30、查询同名同姓学生名单,并统计同名人数-★
SELECT T.SNAME, COUNT(DISTINCT T.SID)
FROM STUDENT T
GROUP BY T.SNAME HAVING COUNT(DISTINCT T.SID) > 1
ORDER BY 1;
--31、查询当前系统时间的年月日(格式如:2021-05-16)
SELECT TO_CHAR(SYSDATE,'yyyy-MM-DD') FORMAT_DATE FROM DUAL;
--32、查询每门课程的平均成绩,结果按平均成绩升序排列,平均成绩相同时,按课程号降序排列-★
SELECT T1.CID, T2.CNAME, ROUND(AVG(T1.SCORE), 2)AVG_SCORE
FROM SC T1
LEFT JOIN COURSE T2 ON T1.CID = T2.CID
GROUP BY T1.CID, T2.CNAME
ORDER BY 3 ASC, 1;
--33、查询平均成绩大于85的所有学生的学号、姓名和平均成绩-★
SELECT T1.SID, T2.SNAME, AVG(T1.SCORE)AVG_SCORE
FROM SC T1
LEFT JOIN STUDENT T2 ON T1.SID = T2.SID
GROUP BY T1.SID, T2.SNAME HAVING AVG(T1.SCORE) > 85
ORDER BY 1;
--34、查询课程名称为"数据库",且分数低于60的学生姓名和分数-★
SELECT T.SID, T2.SNAME, T.SCORE
FROM SC T
LEFT JOIN STUDENT T2
ON T.SID = T2.SID
WHERE T.CID = (SELECT T2.CID FROM COURSE T2 WHERE T2.CNAME = '数据库')
AND T.SCORE < 60
ORDER BY 1;
--35、查询所有学生的选课情况-★
SELECT T3.SID,T3.SNAME,T2.CID, T2.CNAME ,COUNT(DISTINCT T1.CID) 选课情况 FROM SC T1
LEFT JOIN COURSE T2 ON T1.CID=T2.CID
LEFT JOIN STUDENT T3 ON T1.SID=T3.SID
GROUP BY T3.SID,T3.SNAME,T2.CID, T2.CNAME ORDER BY 1,3;
--36、查询任何一门课程成绩在70分以上的姓名、课程名称和分数-★
SELECT T1.SID,T3.SNAME,T2.CNAME,T1.SCORE FROM SC T1
LEFT JOIN COURSE T2 ON T1.CID=T2.CID
LEFT JOIN STUDENT T3 ON T1.SID=T3.SID
WHERE T1.SCORE>70 ORDER BY 4 DESC;
--37、查询不及格的课程,并按课程号从大到小排列-★
SELECT * FROM SC T WHERE T.SCORE<60 ORDER BY T.CID DESC ;
--38、查询课程编号为003且课程成绩在80分以上的学生的学号和姓名-★
SELECT T1.SID, T2.SNAME, T1.SCORE
FROM SC T1
LEFT JOIN STUDENT T2 ON T1.SID = T2.SID
WHERE T1.CID = '001'AND T1.SCORE > 80
ORDER BY 1;
--39、求选了课程的学生人数-★
SELECT COUNT(DISTINCT T.SID) 学生人数 FROM SC T ;
--40、查询选修"叶平"老师所授课程的学生中,成绩最高的学生姓名及其成绩-★★
WITH TEMP_SCORE AS(
SELECT * FROM SC T1
WHERE T1.CID IN(
SELECT T3.CID FROM TEACHER T2 ,COURSE T3 WHERE T2.TNAME='叶平' AND T2.TID=T3.TID )
)
SELECT A.SID,B.SNAME,A.SCORE FROM SC A
LEFT JOIN STUDENT B ON A.SID=B.SID
LEFT JOIN TEMP_SCORE C ON C.SID=A.SID AND C.CID=A.CID
WHERE A.SCORE IN (SELECT MAX(D.SCORE) FROM TEMP_SCORE D);
--41、查询各个课程及相应的选修人数-★
SELECT T.CID,COUNT(DISTINCT T.SID)选修人数 FROM SC T GROUP BY T.CID ORDER BY 1 ;
--42、查询不同课程成绩相同的学生的学号、课程号、学生成绩-★★
SELECT * FROM SC T3
WHERE T3.SCORE IN (
SELECT T1.SCORE FROM SC T1
GROUP BY T1.SCORE HAVING COUNT(DISTINCT T1.CID)>1
) ORDER BY 3 ;
--43、查询每门功成绩最好的前两名-★★★
SELECT *
FROM (SELECT T1.SID,
T1.CID,
T1.SCORE,
RANK() OVER(PARTITION BY T1.CID ORDER BY T1.SCORE DESC NULLS LAST) RANK
FROM SC T1) A
WHERE A.RANK <= 2;
--44、统计每门课程的学生选修人数(超过3人的课程才统计)要求输出课程号和选修人数,查询结果按人数降序排列,查询结果按人数降序排列,若人数相同,按课程号升序排列-★★★
SELECT T1.CID, COUNT(T1.SID) CID_COUNT
FROM SC T1
GROUP BY T1.CID HAVING COUNT(T1.SID) > 3
ORDER BY 2 DESC, 1 ASC;
--45、检索至少选修两门课程的学生学号-★
SELECT T1.SID, T2.SNAME--, COUNT(DISTINCT T1.CID)
FROM SC T1
LEFT JOIN STUDENT T2
ON T1.SID = T2.SID
GROUP BY T1.SID, SNAME
HAVING COUNT(DISTINCT T1.CID) >= 2
ORDER BY 1;
--46、查询全部学生都选修的课程的课程号和课程名-★
SELECT T1.CID, COUNT(DISTINCT T1.SID)
FROM SC T1
GROUP BY T1.CID
HAVING COUNT(DISTINCT T1.SID) = (SELECT COUNT(DISTINCT T2.SID) FROM STUDENT T2);
以上是关于SQL(之一)-SQL经典题目的主要内容,如果未能解决你的问题,请参考以下文章