前言------

AK: ALL Killed

这学期学数据库系统概论,作为一个初学者,必须先熟练掌握SQL的基本查询语句,在完成了老师的SQL50题之后,我把我自己地AK姿势记录下来, 便于回忆之余,也希望对大家有帮助.

"博客要精心雕琢,我是米开朗基罗",  雕琢了两天,然后没保存好,实在是太憋屈了,,,不甘心,现在终于补回来了,可以好好睡了.

自认为是SQL50题查询中最完善的博客,写文章不容易啊,终于知道计算机的书籍为啥都这么贵了....

目录

一.完成这50题之前首先做什么?

二.这50题要怎么做

三.建表并且插入数据

四.给人以鱼,不如授之以渔: 题目精选解析

五.SQL代码大全(不包括日期的题目)


一.完成这50题之前首先做什么?

1.完成第三章的例题

假如你基础知识还基本没掌握:我建议先把<< 数据库系统概论>>(萨师煊)第三章的例题都好好研究一遍, 关键是要自己敲一遍, 这样做的目的是让你对一些连接,查询,分组,聚集函数,谓词查询,Like,IN,ORDER BY等基础知识 有足够的理解和记忆 ,避免做题时,无技巧可用.

2.理解好GROUP BY

分享一篇超好的博客,一看就领悟(超链接)

3.理解好连接

for(枚举表A中的元组 :i){for(枚举表B中的元组:j){for(枚举表C中的元组:k){if(i ,j,k连接而成的元组满足条件)输出i,j,k连接而成的元组}}
}
注:我只是便于理解写的,实际中,一旦不符合就会contine ,效率比我写的运行方式高多了

4.把中文输入法的符号改为英文符号,这绝对能节省一大半的时间

上部分的语句和下部分的语句,差别就在箭头处的符号是中文字符.......这种错误有时很难查找,会让你一脸懵逼的,所以建议大家

禁止掉中文符号!!!!!!!! (以搜狗输入法为例)

二.这50题要怎么做

我觉得这50题当中,比较有价值的题目,或者说稍微有点难度的题目就那么20题,其余都是比较基础的题目.

1.你不能应付作业的形式来对待....要以提升水平来看待

2.在做题的过程中不要去网上查找题解,这点超级重要!!

3.一道题要尽自己所能去想,时间充足的话,一道题可以给自己一小时的时间去思考,遇到不熟悉的知识,可以翻开课本查询

4.如果一道题有思路,但是觉得可能不好写,不要放弃,尽自己所能去模拟出来, 即使你的思路或者解法不是很优秀,但是在你模拟

的中间过程,你获得了调试能力,对知识点理解得更加熟练,这比一不会就看答案强多了.

5.实在不会的可以问老师,同学,如果都没得问的话,可以查找题解,但是一定要做到是自己的,说白了,不会的这道题,在隔了半个月,你还是会做.

三.建表并且插入数据

环境:PostgreSQL 10 ,命令行模式 (都是用书上基本的SQL语句,可以在mySQL,Sqlite等用)

数据表介绍
--1.学生表
Student(Sno,Sname,Sage,Ssex)
--Sno 学生编号,Sname 学生姓名,Sage 出生年月,Ssex 学生性别
--2.课程表
Course(Cno,Cname,Tno)
--Cno 课程编号,Cname 课程名称,Tno 教师编号
--3.教师表
Teacher(Tno,Tname)
--Tno 教师编号,Tname 教师姓名
--4.成绩表
SC(Sno,Cno,Grade)
--Sno 学生编号,Cno 课程编号,Greade 分数

/*
建立Student表,并且插入数据
*/
CREATE TABLE Student(Sno CHAR(9),Sname CHAR(9),Sage date,Ssex CHAR(9)
);
insert into Student values('01' , '赵雷' , '1990-01-01' , '男');
insert into Student values('02' , '钱电' , '1990-12-21' , '男');
insert into Student values('03' , '孙风' , '1990-12-20' , '男');
insert into Student values('04' , '李云' , '1990-12-06' , '男');
insert into Student values('05' , '周梅' , '1991-12-01' , '女');
insert into Student values('06' , '吴兰' , '1992-01-01' , '女');
insert into Student values('07' , '郑竹' , '1989-01-01' , '女');
insert into Student values('09' , '张三' , '2017-12-20' , '女');
insert into Student values('10' , '李四' , '2017-12-25' , '女');
insert into Student values('11' , '李四' , '2012-06-06' , '女');
insert into Student values('12' , '赵六' , '2013-06-13' , '女');
insert into Student values('13' , '孙七' , '2014-06-01' , '女');
/*
插入Course表和数据
*/CREATE TABLE Course(Cno CHAR(9),Cname CHAR(9),Tno  CHAR(9)
);insert into Course values('01' , '语文' , '02');
insert into Course values('02' , '数学' , '01');
insert into Course values('03' , '英语' , '03');
/*
插入Teacher表和数据
*/
CREATE TABLE Teacher(Tno CHAR(9),Tname CHAR(9));insert into Teacher values('01' , '张三');
insert into Teacher values('02' , '李四');
insert into Teacher values('03' , '王五');
/*
创建SC表,并且插入数据
*/
CREATE TABLE SC(Sno CHAR(9),Cno CHAR(9),Grade SMALLINT
);
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);

四.给人以鱼,不如授之以渔: 题目精选解析

  • 类型一:聚集函数的使用

题目:查询各科成绩最高分、最低分和平均分

SQL代码:

SELECT Cno,MAX(Grade) AS 最高分,MIN(Grade) AS 最低分,AVG(Grade) AS 平均分
FROM SC
GROUP BY Cno;
  • 类型二:外连接的使用

题目:查询存在" 01 "课程但可能不存在" 02 "课程的情况(不存在时显示为 null )

分析:

第一步:先用SC派生出一张只选修01的表 ,x表

第二步:用SC派生出一张只选修02的表,y表

第三步:用x表左外连接y表(题目要求不存在时显示为NULL),这样才能保证选修了01课程的学生都可以输出

SQL代码:

SELECT x.*,y.Cno,y.Grade
FROM   (SELECT *FROM SC xWHERE Cno ='01')  AS xLEFT OUTER JOIN ( SELECT *FROM SC WHERE Cno ='02') AS y ON (x.Sno = y.Sno);
  • 类型三:通配符的使用

题目: 查询名字中含有「风」字的学生信息

分析: %代表任意个字符

SQL代码:

SELECT *
FROM Student
WHERE Sname LIKE '%风%';
  • 类型四.嵌套查询和谓词IN的使用(优点:结构清晰)

题目:查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩

分析:

第一步:我们依次枚举每个学生,

第二步每当我们枚举一个学生,就应该判断该该学会是不是属于"两门及其以上不及格课程的"的学号集合中;

第三步:所以我们要去找出"两门及其以上不及格课程的"的学号集合"

第四步:确定了在上述集合中后,我们认定这个学生应该输出,但是要输出平均成绩怎么办呢?在输出平均成绩的时候,在SELECT中计算平均成绩,计算后再作为一个属性输出.

SQL代码:

SELECT Student.*,     (SELECT AVG(Grade)FROM SCWHERE SC.Sno = Student.Sno) AS 平均成绩
FROM Student
WHERE Sno IN (SELECT SnoFROM  SC WHERE Grade < 60GROUP BY SnoHAVING COUNT(Grade) >=2);
  • 类型五:多字段分组的使用

题目:按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩(同时要求输出学生姓名)

分析:

第一步:肯定是拿SC表和Student表按学号进行连接

第二步:考虑分组,那么按学号分组的话,是无法输出姓名的,所以考虑多字段分组,按(Student.Sno ,Sname)进行分组,这样就可以输出姓名了

SQL代码:

SELECT Student.Sno ,Sname,AVG(Grade) AS 平均成绩
FROM SC,Student
WHERE SC.Sno = Student.Sno
GROUP BY Student.Sno ,Sname
ORDER BY 平均成绩 DESC;
  • 类型六:ORDER BY的使用  (DESC是降序,ASC是升序)

注:在PostgreSQL中降序的关键字是ASC,在其他关系型数据库中可能是AESC

题目:检索" 01 "课程分数小于 60,按分数降序排列的学生信息

SQL代码:

SELECT Student.*,Grade
FROM SC,Student
WHERE Student.Sno = SC.Sno AND  SC.Cno = '01' AND SC.Grade < 60
ORDER BY SC.Grade DESC;

​​​​​​​

  • 类型七.EXISTS查询

题目:查询没学过"张三"老师讲授的任一门课程的学生姓名

分析:

第一步: 如果一个学生 x满足  " 没学过"张三"老师讲授的任一门课程的学生姓名​​​ ",那么可以等价转化为什么条件呢?

第二步:等价条件: 对于学生x,  他选修的所有课程, 肯定"不存在一门课程属于张三老师讲授的课程"

分析完后,我们就可以快速地写出来了

SQL代码:

SELECT Sname
FROM Student x
WHERE NOT EXISTS(SELECT*FROM SC yWHERE  y.Sno = x.Sno AND  EXISTS(SELECT*FROM Teacher,CourseWHERE Teacher.Tno = Course.Tno AND y.Cno = Course.Cno  AND Teacher.Tname ='张三' ));

​​​​​​​

  • 类型八.EXISTS查询易错类型

题目: 查询和" 01 "号的同学学习的课程 完全相同的其他同学的信息

分析:这道题有"完全"的字眼,一眼看上去,就想用EXISTS查询解决,但是后面查询结果是错的, 感觉用EXISTS查询做还是挺容易出错的

(嘻嘻,也可能是我太菜了~~)

第一步:我们先思考: 如果有个同学 x,学习的课程和"01"号同学完全相同,那么这个同学符合什么条件呢?

第二步::概括上述的条件:对于x,他选修的所有课程,  肯定"不存在一门课程是不在01同学的课程内的"

概括出了第二步的条件,我很自然地写出了下面错误的SQL:

SELECT x.*
FROM Student x
WHERE x.Sno != '01' AND NOT EXISTS(SELECT*FROM SC yWHERE y.Sno = x.Sno AND NOT EXISTS(SELECT*FROM SC zWHERE z.Sno ='01' AND z.Cno = y.Cno));

为什么会错了,,我画个图就明白了:

大家懂了吧!!上面的SQL代码查询出来的同学, 他们选修课程是01同学选修课程的子集,如图所示,a同学和b同学也会被筛选出来,但是他们明显不符合我们的结果  ......题目要求的是完全相同, 也就是要求等集,那么我们该怎么改进呢?

把第二步条件改为:  对于x,他选修的所有课程,  肯定"不存在一门课程是不在01同学的课程内的  && x选修的课程数等于01所选修的课程数"

正确SQL代码(非EXISTS查询):

分析:

第一步:拿两张SC表, 分别为x,y. 然后按照 x.Sno !='01' AND y.Sno = '01' AND x.Cno = y.Cno进行连接.  找出选修(01选修的课程)

的记录, 由于这边还要输出学生的姓名,所以我们拿张Student表继续连接,以便输出姓名等信息

第二步:对第一步得到的表按照( Student.Sname,Student.Sno )进行分组, 然后用聚集函数判断该学生选修的(01选修的课程) 数是否和01同学相同

SQL代码:

SELECT Student.Sname,Student.Sno
FROM  SC x,SC y,Student
WHERE Student.Sno =x.Sno AND x.Sno !='01' AND y.Sno = '01' AND x.Cno = y.Cno
GROUP BY Student.Sname,Student.Sno
HAVING COUNT(y.Cno) =(SELECT COUNT(*)FROM SCWHERE  SC.Sno ='01'); 
  • 类型九.按某种属性排名,要求重复时 保留名次空缺

什么是保留名次空缺:

姓名   成绩   排名
小A     99     1
小B     99     1
小C     98     3/*
这里小C的98分虽然是第2高分,但是它是年级第三名.因为第一名并列2个,因此第2的名次就空缺了
像这种排列方法,就称为保留名次空缺.每个人的名次 = 比我考得高分的人的数量 + 1
*/

​​​​​​​题目:按各科成绩进行排序,并显示排名, Score 重复时保留名次空缺

分析:

第一步: 拿两张SC表,一张为x, 一张为y, 然后按照x.Cno = y.Cno AND y.Grade > x.Grade进行连接,目的是派生出一张表:

该表可以显示看对于某学生的某个科目,有多少人考得比它高. 当然了,还要按照( x.Sno,x.Cno,x.Grade)进行分组,

COUNT( y.Grade) + 1就是名次了 (没有加DISTINCE是默认不会去重的),该表称为xx

第二步:拿Student表和xx表进行连接,以便输出姓名等信息

SQL代码:

​
SELECT Student.*,xx.Cno,xx.Grade,xx.名次
FROM (SELECT x.Sno,x.Cno,x.Grade, COUNT(y.Grade) + 1 AS 名次FROM SC AS x LEFT OUTER JOIN SC AS y ON (x.Cno = y.Cno AND y.Grade > x.Grade)GROUP BY x.Sno,x.Cno,x.Grade) AS xx,Student
WHERE Student.Sno = xx.Sno
ORDER BY xx.Cno, xx.名次;​

  • 类型10.按某种属性排名,要求重复时 不保留名次空缺

什么是不保留名次空缺:

姓名   成绩   排名
小A     99     1
小B     99     1
小C     98     2/*
这里小C的98分是第2高分,,因此第2的名次就没有空缺了
像这种排列方法,就称为不保留名次空缺.每个人的名次 = (>=我的分数类型有几种 )
*/

题目:按各科成绩进行排序,并显示排名, Score 重复时合并名次(不保留名次空缺)

分析:

第一步: 拿两张SC表,一张为x, 一张为y, 然后按照x.Cno = y.Cno AND y.Grade > x.Grade进行连接,目的是派生出一张表:

该表可以显示看对于出某学生的某个科目,有多少人考得比它高. 当然了,还要按照( x.Sno,x.Cno,x.Grade)进行分组, COUNT(DISTINCT y.Grade) 就是 >=我的分数类型的种类数,也就是名次,  把这张表命名为xx

第二步:拿Student表和xx表进行连接,以便输出姓名等信息

SQL代码:

SELECT xx.*,xx.Cno, xx.名次
FROM ( SELECT x.Sno,x.Cno, COUNT(DISTINCT y.Grade) AS 名次FROM SC AS x LEFT OUTER JOIN SC AS y ON (x.Cno = y.Cno AND y.Grade >= x.Grade)GROUP BY x.Sno,x.Cno) AS xx,Student
WHERE Student.Sno = xx.Sno
ORDER BY xx.Cno, xx.名次;

  • 类型11:输出优秀率或者及格率的题目

题目:以如下形式显示:课程 ID,课程 name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率
及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90 (且要求输出课程号和选修人数,查询结果按选修人数降序排列,若人数相同,按课程号升序排列)  括号部分是我把另外一题合并进来的,更综合

分析:

第一步:首先生成4张派生表:a,b,c,d.   a表用来统计各科优秀的人数    b表用来统计各科优良的人数  c表用来统计各科中等的人数

d表用来统计各科及格的人数

/*d表*/
SELECT Course.Cno, COUNT(Grade) AS 及格人数
FROM Course LEFT OUTER JOIN SC ON (Course.Cno = SC.Cno AND SC.Grade >=60)
GROUP BY Course.Cno;/*c表*/
SELECT Course.Cno, COUNT(Grade) AS 中等人数
FROM Course LEFT OUTER JOIN SC ON (Course.Cno = SC.Cno AND Grade >=70 AND Grade <80)
GROUP BY Course.Cno;/*b表*/
SELECT Course.Cno, COUNT(Grade) AS 优良人数
FROM Course LEFT OUTER JOIN SC ON (Course.Cno = SC.Cno AND Grade >=80 AND Grade <90)
GROUP BY Course.Cno ;/*a表*/
SELECT Course.Cno, COUNT(Grade) AS 优秀人数
FROM Course LEFT OUTER JOIN SC ON (Course.Cno = SC.Cno AND Grade >=90)
GROUP BY Course.Cno ;

第二步:生成派生表x,该表记录了各科的最高分,最低分,平均分,选修总人数

/*派生表*/SELECT Course.Cno ,MAX(Grade) AS 最高分 ,COUNT(*) AS 选修人数, MIN(Grade) AS 最低分 ,AVG(Grade) AS 平均分
FROM Course LEFT OUTER JOIN SC ON (Course.Cno = SC.Cno )
GROUP BY Course.Cno;

第三步. a,b,c,d,x这5张表进行连接,并且对结果进行排序

SQL代码:

SELECT x.Cno AS 课程ID ,Course.Cname AS 课程name,  x.选修人数,x.最高分,x.最低分 ,x.平均分 ,d.及格人数*1.0/x.选修人数 AS 及格率 ,c.中等人数*1.0/x.选修人数 AS  中等率,b.优良人数*1.0/x.选修人数 AS 优良率, a.优秀人数*1.0/x.选修人数 AS 优秀率
FROM (SELECT Course.Cno, COUNT(Grade) AS 及格人数FROM Course LEFT OUTER JOIN SC ON  (Course.Cno = SC.Cno AND Grade >=60)GROUP BY Course.Cno ) AS d ,(SELECT Course.Cno, COUNT(Grade) AS 中等人数FROM  Course LEFT OUTER JOIN SC ON  (Course.Cno = SC.Cno AND Grade>=70 AND Grade <80)GROUP BY Course.Cno ) AS c ,(SELECT Course.Cno, COUNT(Grade) AS 优良人数FROM Course LEFT OUTER JOIN SC ON  (Course.Cno = SC.Cno AND Grade >=80 AND Grade <90)GROUP BY Course.Cno ) AS b,(SELECT Course.Cno, COUNT(Grade) AS 优秀人数FROM Course LEFT OUTER JOIN SC ON  (Course.Cno = SC.Cno AND Grade >=90)GROUP BY Course.Cno ) AS a ,(SELECT Course.Cno ,MAX(Grade) AS 最高分 ,COUNT(*) AS 选修人数, MIN(Grade) AS 最低分 ,AVG(Grade) AS 平均分FROM  Course LEFT OUTER JOIN SC ON  (Course.Cno = SC.Cno )GROUP BY Course.Cno) AS x ,CourseWHERE d.Cno = c.Cno AND c.Cno = b.Cno AND b.Cno = a.Cno AND a.Cno = x.Cno AND x.Cno = Course.Cno
ORDER BY 选修人数 DESC, 课程ID ASC;

  • 类型十二: 查询各科前几名的记录

题目:查询各科成绩前三名的记录

分析:  这种查排名的题目,第一反应是要不要保留名次空缺,这题没有提到,说明题目不严谨

保留名次空缺:核心思想跟类型9一样

第一步:拿出两张SC表,分别为x,y表, 用x表去左外连接y表, 这边要用外连接,! 不然第一名的人由于没有人分数比他高, 无法被筛选,

连接后, 对于某个人的某个科目,都能直接看出有多少人比他高

第二步:对第一步的表按(Student.Sname,Student.Sno,x.Cno)进行分组. 再用HAVING语句筛选 COUNT(y.Grade) < 3的分组

SQL代码:

SELECT Student.Sname,Student.Sno,x.Cno,COUNT(y.Grade) + 1 AS 名次
FROM SC AS x LEFT OUTER JOIN SC AS y ON  (x.Cno = y.Cno AND y.Grade > x.Grade),Student
WHERE x.Sno = Student.Sno
GROUP BY Student.Sname,Student.Sno,x.Cno
HAVING COUNT(y.Grade) < 3
ORDER BY x.Cno DESC, 名次 ASC;

不保留名次空缺:核心思想跟类型10一样

分析: 主要是一些条件变化了,直接看SQL代码比较差异,差异的原因请看类型10

SQL代码:

SELECT Student.Sname,Student.Sno,x.Cno,COUNT(DISTINCT y.Grade) AS 名次
FROM SC AS x LEFT OUTER JOIN SC AS y ON  (x.Cno = y.Cno AND y.Grade > x.Grade),Student
WHERE x.Cno = y.Cno AND y.Grade >= x.Grade AND Student.Sno = x.Sno
GROUP BY Student.Sname,Student.Sno,x.Cno
HAVING COUNT(DISTINCT y.Grade) <= 3
ORDER BY x.Cno DESC, 名次 ASC;
  • 类型13.  WHERE,GROUP BY ,HAVING ,ORDER BY的混合使用

题目:查询平均成绩大于等于 60 分的同学的学生编号和学生姓名和平均成绩,结果按平均成绩进行降序排列

分析:

第一步:执行WHERE语句,把Student和SC表进行连接,形成一张表,暂且称为x

第二步:按照( Student.Sno,Sname)对x表进行分组

第三步:执行HAVING语句,对每个分组进行筛选,筛选出AVG(SC.Grade) >=60的分组, 形成一张表,暂且称为y表

第四步:执行SELECT语句,筛选出字段,称为z表

第五步:执行ORDER BY语句, 对z表进行排序,按照成绩进行降序排序,称为结果表

SQL代码:

SELECT Student.Sno,Sname,AVG(SC.Grade) AS 平均成绩
FROM Student,SC
WHERE Student.Sno = SC.Sno
GROUP BY Student.Sno,Sname
HAVING AVG(SC.Grade) >=60
ORDER BY 平均成绩 DESC;
  • 类型14.查询任意成绩都大于某个值的信息

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

分析:

第一步:拿出一张SC表 ,筛选出成绩>=70的选课记录

第二步:对第一步的表按x.Sno进行分组, 再用聚集函数筛选出 (>=70分的课程数) = (该学生选修的课程数)的分组.  称为xx表

第三步:用xx表和Student,SC表进行连接,以便输出姓名,课程名称

SQL代码:

SELECT Student.Sname, xx.Sno,Course.Cname,z.Grade
FROM    (SELECT x.SnoFROM   SC xWHERE  x.Grade >=70GROUP BY x.SnoHAVING COUNT(x.Grade) = (SELECT COUNT(*)FROM SC yWHERE y.Sno = x.Sno )) AS xx, Course,Student,SC z
WHERE xx.Sno = Student.Sno AND z.Sno = xx.Sno AND Course.Cno = z.Cno;
  • 类型15.查询选修某老师所授课程的学生中,成绩最高的学生信息及其成绩

题目:成绩有重复的情况下,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩

题目:成绩不重复,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩

分析:这道题,由于是只求最高分,  我的解法适用于成绩有重复和不重复的两种情况.

第一步:拿Course, Teacher,SC表进行连接,

第二步:由于1个老师可能教授多门课程,且有可能叫"张三"的老师又多个, 所以我们要按照(Teacher.Tno,SC.Cno)进行分组,并且筛选

出对应的字段,  其中一个字段就是某个课程的最高分 ,称为x表

第三步,再拿出一张SC表 ,Student表, 和x表进行连接 ,连接条件是:SC.Grade = x.MaxGrade AND SC.Cno = x.Cno AND Student.sno = SC.Sno,形成结果表

SQL代码:

SELECT  Student.*,SC.Cno,SC.Grade
FROM    (SELECT Teacher.Tno,  SC.Cno,MAX(SC.Grade) AS MaxGradeFROM  Course ,Teacher,SCWHERE Course.Tno = Teacher.Tno AND Course.Cno = SC.Cno  AND Teacher.Tname ='张三'GROUP BY Teacher.Tno,SC.Cno)AS x, SC,StudentWHERE SC.Grade = x.MaxGrade AND SC.Cno = x.Cno AND Student.sno = SC.Sno;

​​​​​​​

  • 类型16.日期类型

分析:不同的关系型数据库,日期类型和对应的函数都不 尽相同, 可以去官方查询对应的文档,这边忽略了

五.SQL代码大全(不包括日期的题目)

//1.查询" 01 "课程比" 02 "课程成绩高的学生的信息及课程分数SELECT Student.*,x.Grade AS 课程1,y.Grade AS 课程2
FROM SC x,SC y,Student
WHERE Student.Sno = x.Sno AND x.Sno = y.Sno AND x.Cno ='01' AND y.Cno ='02' AND x.Grade > y.Grade;//2.查询同时存在" 01 "课程和" 02 "课程的情况
SELECT DISTINCT x.Sno
FROM  SC x, SC y
WHERE x.Sno = y.Sno AND x.Cno ='01' AND y.Cno ='02';//3.查询存在" 01 "课程但可能不存在" 02 "课程的情况(不存在时显示为 null )
SELECT x.*,y.Cno,y.Grade
FROM   (SELECT *FROM SC xWHERE Cno ='01')  AS xLEFT OUTER JOIN ( SELECT *FROM SC WHERE Cno ='02') AS y ON (x.Sno = y.Sno);//4.查询不存在" 01 "课程但存在" 02 "课程的情况
SELECT  x.Sno
FROM SC x
WHERE x.Cno ='02' AND x.Sno  NOT IN(SELECT DISTINCT y.SnoFROM SC yxWHERE y.Cno ='01');//5.查询平均成绩大于等于 60 分的同学的学生编号和学生姓名和平均成绩,结果按平均成绩进行降序排列
SELECT Student.Sno,Sname,AVG(SC.Grade) AS 平均成绩
FROM Student,SC
WHERE Student.Sno = SC.Sno
GROUP BY Student.Sno,Sname
HAVING AVG(SC.Grade) >=60
ORDER BY 平均成绩 DESC;//6.查询在 SC 表存在成绩的学生信息
SELECT Student.*
FROM Student
WHERE Student.Sno IN (SELECT SC.SnoFROM SC GROUP BY SC.Sno
);//7.查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩(没成绩的显示为 null )
SELECT Student.Sno,Student.Sname,x.COUNT,x.SUM
FROM Student LEFT OUTER JOIN (SELECT SC.Sno ,COUNT(SC.Cno),SUM(SC.Grade)FROM SCGROUP BY SC.Sno) AS x ON (Student.Sno = x.Sno);// 8.查询「李」姓老师的数量
SELECT COUNT(*)
FROM Teacher
WHERE Tname Like '李%';//9.查询学过「张三」老师授课的同学的信息
SELECT ALL Student.*
FROM Course,Teacher,SC,Student
WHERE SC.Cno = Course.Cno AND SC.Sno = Student.Sno AND Course.Tno = Teacher.Tno AND Teacher.Tname ='张三';//10.查询没有学全所有课程的同学的信息
SELECT *
FROM Student
WHERE EXISTS(SELECT*FROM CourseWHERE NOT EXISTS(SELECT*FROM SCWHERE SC.Sno= Student.Sno AND Course.Cno = SC.Cno ));//11.查询至少有一门课与学号为" 01 "的同学所学相同的同学的信息
SELECT DISTINCT Sno
FROM SC x
WHERE  EXISTS(SELECT*FROM SC yWHERE y.Sno = x.Sno AND  EXISTS(SELECT *FROM SC zWHERE z.Sno ='01' AND z.Cno = y.Cno));//12.查询和" 01 "号的同学学习的课程 完全相同的其他同学的信息SELECT Student.Sname,Student.Sno
FROM  SC x,SC y,Student
WHERE Student.Sno =x.Sno AND x.Sno !='01' AND y.Sno = '01' AND x.Cno = y.Cno
GROUP BY Student.Sname,Student.Sno
HAVING COUNT(y.Cno) =(SELECT COUNT(*)FROM SCWHERE  SC.Sno ='01'); //13.查询没学过"张三"老师讲授的任一门课程的学生姓名
SELECT Sname
FROM Student x
WHERE NOT EXISTS(SELECT*FROM SC yWHERE  y.Sno = x.Sno AND  EXISTS(SELECT*FROM Teacher,CourseWHERE Teacher.Tno = Course.Tno AND y.Cno = Course.Cno  AND Teacher.Tname ='张三' ));//14.查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
SELECT Student.*,     (SELECT AVG(Grade)FROM SCWHERE SC.Sno = Student.Sno) AS 平均成绩
FROM Student
WHERE Sno IN (SELECT SnoFROM  SC WHERE Grade < 60GROUP BY SnoHAVING COUNT(Grade) >=2);//15.检索" 01 "课程分数小于 60,按分数降序排列的学生信息
SELECT Student.*,Grade
FROM SC,Student
WHERE Student.Sno = SC.Sno AND  SC.Cno = '01' AND SC.Grade < 60
ORDER BY SC.Grade DESC;//16.按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
SELECT Student.Sno ,Sname,AVG(Grade) AS 平均成绩
FROM SC,Student
WHERE SC.Sno = Student.Sno
GROUP BY Student.Sno ,Sname
ORDER BY 平均成绩 DESC;//17.查询各科成绩最高分、最低分和平均分:
SELECT Cno,MAX(Grade) AS 最高分,MIN(Grade) AS 最低分,AVG(Grade) AS 平均分
FROM SC
GROUP BY Cno;//18.以如下形式显示:课程 ID,课程 name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率
及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90
要求输出课程号和选修人数,查询结果按选修人数降序排列,若人数相同,按课程号升序排列SELECT x.Cno AS 课程ID ,Course.Cname AS 课程name,  x.选修人数,x.最高分,x.最低分 ,x.平均分 ,d.及格人数*1.0/x.选修人数 AS 及格率 ,c.中等人数*1.0/x.选修人数 AS  中等率,b.优良人数*1.0/x.选修人数 AS 优良率, a.优秀人数*1.0/x.选修人数 AS 优秀率
FROM (SELECT Course.Cno, COUNT(Grade) AS 及格人数FROM Course LEFT OUTER JOIN SC ON  (Course.Cno = SC.Cno AND Grade >=60)GROUP BY Course.Cno ) AS d ,(SELECT Course.Cno, COUNT(Grade) AS 中等人数FROM  Course LEFT OUTER JOIN SC ON  (Course.Cno = SC.Cno AND Grade>=70 AND Grade <80)GROUP BY Course.Cno ) AS c ,(SELECT Course.Cno, COUNT(Grade) AS 优良人数FROM Course LEFT OUTER JOIN SC ON  (Course.Cno = SC.Cno AND Grade >=80 AND Grade <90)GROUP BY Course.Cno ) AS b,(SELECT Course.Cno, COUNT(Grade) AS 优秀人数FROM Course LEFT OUTER JOIN SC ON  (Course.Cno = SC.Cno AND Grade >=90)GROUP BY Course.Cno ) AS a ,(SELECT Course.Cno ,MAX(Grade) AS 最高分 ,COUNT(*) AS 选修人数, MIN(Grade) AS 最低分 ,AVG(Grade) AS 平均分FROM  Course LEFT OUTER JOIN SC ON  (Course.Cno = SC.Cno )GROUP BY Course.Cno) AS x ,CourseWHERE d.Cno = c.Cno AND c.Cno = b.Cno AND b.Cno = a.Cno AND a.Cno = x.Cno AND x.Cno = Course.Cno
ORDER BY 选修人数 DESC, 课程ID ASC;//19.按各科成绩进行排序,并显示排名, Score 重复时保留名次空缺
SELECT Student.*,xx.Cno,xx.Grade,xx.名次
FROM (SELECT x.Sno,x.Cno,x.Grade, COUNT(y.Grade) + 1 AS 名次FROM SC AS x LEFT OUTER JOIN SC AS y ON (x.Cno = y.Cno AND y.Grade > x.Grade)GROUP BY x.Sno,x.Cno,x.Grade) AS xx,Student
WHERE Student.Sno = xx.Sno
ORDER BY xx.Cno, xx.名次;//20.按各科成绩进行排序,并显示排名, Score 重复时合并名次
SELECT xx.*,xx.Cno, xx.名次
FROM ( SELECT x.Sno,x.Cno, COUNT(DISTINCT y.Grade) AS 名次FROM SC AS x LEFT OUTER JOIN SC AS y ON (x.Cno = y.Cno AND y.Grade >= x.Grade)GROUP BY x.Sno,x.Cno) AS xx,Student
WHERE Student.Sno = xx.Sno
ORDER BY xx.Cno, xx.名次;//21.查询学生的总成绩,并进行排名,总分重复时保留名次空缺
SELECT  x.Sno,x.总分,COUNT( y.总分) + 1 AS 名次
FROM( SELECT Sno,SUM(Grade) AS 总分FROM  SC GROUP BY Sno) AS x LEFT OUTER JOIN ( SELECT Sno,SUM(Grade) AS 总分FROM SCGROUP BY Sno) AS y  ON(y.总分 > x.总分)      GROUP BY x.Sno,x.总分
ORDER BY x.总分 DESC;//22.查询学生的总成绩,并进行排名,总分重复时不保留名次空缺
SELECT  x.Sno,Sname,x.总分,COUNT(DISTINCT y.总分) AS 名次
FROM( SELECT Student.Sno,Sname,SUM(Grade) AS 总分FROM  Student LEFT OUTER JOIN SC ON(Student.Sno = SC.Sno )GROUP BY Student.Sno,Sname) AS x LEFT OUTER JOIN ( SELECT Sno,SUM(Grade) AS 总分FROM SCGROUP BY Sno) AS y  ON(y.总分 >= x.总分)      GROUP BY x.Sno,x.Sname,x.总分
ORDER BY x.总分 DESC;//23.统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[60-0] 及所占百分比SELECT x.Cno AS 课程编号,x.Cname AS 课程名称,d.D*1.0/x.总人数 AS D比例, c.C*1.0/x.总人数 AS C比例,b.B*1.0/x.总人数 AS B比例, a.A*1.0/x.总人数 AS A比例
FROM ( SELECT Course.Cno ,COUNT(SC.Grade) AS DFROM Course LEFT OUTER JOIN SC ON (SC.Cno = Course.Cno AND SC.Grade >=0 AND SC.Grade <60)GROUP BY Course.Cno) AS d,( SELECT  Course.Cno ,COUNT(SC.Grade) AS CFROM Course LEFT OUTER JOIN SC ON (SC.Cno = Course.Cno AND SC.Grade >=60 AND SC.Grade <70)覆盖 GROUP BY Course.Cno) AS c,( SELECT  Course.Cno ,COUNT(SC.Grade) AS BFROM Course LEFT OUTER JOIN SC ON (SC.Cno = Course.Cno AND SC.Grade >=70 AND SC.Grade<85)GROUP BY Course.Cno) AS b,( SELECT  Course.Cno ,COUNT(SC.Grade) AS AFROM Course LEFT OUTER JOIN SC ON (SC.Cno = Course.Cno AND SC.Grade >=85 AND SC.Grade < 100)GROUP BY Course.Cno) AS a,( SELECT Course.Cno ,Course.Cname,COUNT(SC.Grade) AS 总人数FROM Course LEFT OUTER JOIN SC ON (SC.Cno = Course.Cno)GROUP BY Course.Cno,Course.Cname) AS x
WHERE a.Cno = b.Cno AND b.Cno = c.Cno AND c.Cno = d.Cno AND d.Cno = x.Cno;//24.查询每门课程被选修的学生数
SELECT Course.Cno,Course.Cname,COUNT(SC.Sno) AS 学生数
FROM Course LEFT OUTER JOIN SC ON (SC.Cno = Course.Cno)
GROUP BY Course.Cno,Course.Cname;//25 .查询各科成绩前三名的记录
保留名次空缺:
SELECT Student.Sname,Student.Sno,x.Cno,COUNT(y.Grade) + 1 AS 名次
FROM SC AS x LEFT OUTER JOIN SC AS y ON  (x.Cno = y.Cno AND y.Grade > x.Grade),Student
WHERE x.Sno = Student.Sno
GROUP BY Student.Sname,Student.Sno,x.Cno
HAVING COUNT(y.Grade) < 3
ORDER BY x.Cno DESC, 名次 ASC;//不保留名次空缺
SELECT Student.Sname,Student.Sno,x.Cno,COUNT(DISTINCT y.Grade) AS 名次
FROM SC AS x LEFT OUTER JOIN SC AS y ON  (x.Cno = y.Cno AND y.Grade > x.Grade),Student
WHERE x.Cno = y.Cno AND y.Grade >= x.Grade AND Student.Sno = x.Sno
GROUP BY Student.Sname,Student.Sno,x.Cno
HAVING COUNT(DISTINCT y.Grade) <= 3
ORDER BY x.Cno DESC, 名次 ASC;//26.查询出只选修两门课程的学生学号和姓名
SELECT Student.Sno,Sname
FROM Student LEFT OUTER JOIN SC ON (SC.Sno = Student.Sno)
GROUP BY Student.Sno,Sname
HAVING COUNT(SC.Cno) =2;//27.查询男生、女生人数
SELECT Ssex,COUNT(*) AS 人数
FROM Student
GROUP BY Ssex;//28.查询名字中含有「风」字的学生信息
SELECT *
FROM Student
WHERE Sname LIKE '%风%';//29.查询同名同性学生名单,并统计同名人数
SELECT x.Sname, COUNT(y.Sname) AS 人数
FROM Student x,Student y
WHERE x.Sname =y.Sname AND x.Ssex = y.Ssex AND x.Sno !=y.Sno
GROUP BY x.Sname;//30.查询 1990 年出生的学生名单
SELECT Student.*
FROM Student
WHERE extract(year from Sage) = 1990;//31.查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
SELECT Cno,AVG(Grade) AS 平均成绩
FROM SC
GROUP BY Cno
ORDER BY 平均成绩 DESC, Cno ASC; //32.查询平均成绩大于等于 85 的所有学生的学号、姓名和平均成绩
SELECT x.Sno,Student.Sname,AVG(y.Grade) AS 平均成绩
FROM SC x, SC y,Student
WHERE x.Sno = y.Sno AND Student.Sno = y.Sno
GROUP BY x.Sno,Student.Sname
HAVING AVG(y.Grade) >= 85;//33.查询课程名称为「数学」,且分数低于 60 的学生姓名和分数
SELECT Student.Sname,SC.Grade
FROM Student, SC,Course
WHERE Student.Sno = SC.Sno AND SC.Cno = Course.Cno AND Course.Cname ='数学'AND SC.Grade <60;//34.查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)
SELECT Student.*,SC.Cno ,Course.Cname ,SC.Grade
FROM Student LEFT OUTER JOIN SC ON (Student.Sno = SC.Sno)  LEFT OUTER JOIN Course ON (Course.Cno = SC.Cno);//35.查询任何一门课程成绩在 70 分以上的姓名、课程名称和分数
SELECT Student.Sname, xx.Sno,Course.Cname,z.Grade
FROM    (SELECT x.SnoFROM   SC xWHERE  x.Grade >=70GROUP BY x.SnoHAVING COUNT(x.Grade) = (SELECT COUNT(*)FROM SC yWHERE y.Sno = x.Sno )) AS xx, Course,Student,SC z
WHERE xx.Sno = Student.Sno AND z.Sno = xx.Sno AND Course.Cno = z.Cno;//36.查询不及格的课程
SELECT  Student.*,SC.Cno,Course.Cname,SC.Grade
FROM SC,Student,Course
WHERE SC.Sno = Student.Sno AND SC.Cno = Course.Cno AND SC.Grade < 60;//37.查询课程编号为 01 且课程成绩在 80 分以上的学生的学号和姓名
SELECT Student.Sno ,Student.Sname,SC.Cno,Course.Cname,SC.Grade
FROM SC ,Student,Course
WHERE SC.Sno = Student.Sno AND SC.Cno = Course.Cno AND SC.Cno = '01' AND SC.Grade >=80;//38.求每门课程的学生人数
SELECT Course.Cno,Course.Cname,COUNT(*) AS 选修人数
FROM Course LEFT OUTER JOIN SC ON (SC.Cno = Course.Cno)
GROUP BY Course.Cno,Course.Cname;//39.成绩不重复,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩
SELECT  Student.*,SC.Cno,SC.Grade
FROM    (SELECT Teacher.Tno,  SC.Cno,MAX(SC.Grade) AS MaxGradeFROM  Course ,Teacher,SCWHERE Course.Tno = Teacher.Tno AND Course.Cno = SC.Cno  AND Teacher.Tname ='张三'GROUP BY Teacher.Tno,SC.Cno)AS x, SC,StudentWHERE SC.Grade = x.MaxGrade AND SC.Cno = x.Cno AND Student.sno = SC.Sno;//40.成绩有重复的情况下,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩
SELECT  Student.*,x.SC.Cno,SC.Grade
FROM    (SELECT Teacher.Tno,  SC.Cno,MAX(SC.Grade) AS MaxGradeFROM  Course ,Teacher,SCWHERE Course.Tno = Teacher.Tno AND Course.Cno = SC.Cno  AND Teacher.Tname ='张三'GROUP BY Teacher.Tno,SC.Cno)AS x, SC,StudentWHERE SC.Grade = x.MaxGrade AND SC.Cno = x.Cno AND Student.sno = SC.Sno;//41.查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩
SELECT x.Sno, x.Cno As Cno1 ,y.Cno As Con2,x.Grade AS 相同成绩
FROM SC x ,SC y
WHERE x.Grade = y.Grade AND x.Sno = y.Sno AND x.Cno != y.Cno;//42.查询每门功成绩最好的前两名SELECT x.Sno,x.Cno,x.Grade ,COUNT(y.Grade) AS CntFROM SC AS x LEFT OUTER JOIN SC AS y ON (x.Cno = y.Cno AND y.Grade >x.Grade)GROUP BY x.Sno,x.Cno,x.GradeHAVING COUNT(y.Grade)  < 2;//43.查询选修了全部课程的学生信息
SELECT *
FROM Student x
WHERE NOT EXISTS(SELECT*FROM Course yWHERE  NOT EXISTS(SELECT*FROM SC zWHERE z.Sno = x.Sno AND z.Cno = y.Cno ));

如何以正确地姿势AK SQL查询50题(精华篇)相关推荐

  1. 【SQL经典50题】9.查询和“ 01 “号的同学学习的课程完全相同的其他同学的信息【正解】

    查询所用的表结构见https://blog.csdn.net/zjhbeautiful/article/details/108065336 SQL经典50题第9题正解 题目:查询和" 01 ...

  2. abap 取日期最大_Pointer干货分享:SQL面试50题思路解答与分类整理(下)CASE与日期函数...

    这是POINT小数点的第 368篇文章点点写在前面:SQL技能是数据分析师面试中必不可少的环节,小数点数据社区也给大家提供了练习SQL题目的地方,以下是pointer Yongfan整理的SQL50题 ...

  3. max日期最大值为0_【SQL】SQL面试50题思路解答与分类整理(下)CASE与日期函数...

    题目快速查找索引 阅读指南 上篇 [第一部分]聚合函数(sum/avg/count/min/max) [第二部分]表连接(inner join/left join/right join/full jo ...

  4. 练习总结sql面试50题(2021-12-27完结)

    参考 [数据分析]- SQL面试50题 - 跟我一起打怪升级 一起成为数据科学家_哔哩哔哩_bilibili 图解SQL面试题:经典50题 - 知乎 sql面试题:topN问题 sql 分组查询 分组 ...

  5. 常见的SQL笔试题和面试题:SQL经典50题

    常见的SQL笔试题和面试题(上):经典50题 已知有如下4张表: 学生表:STUDENT(S#,SNAME,SAGE,SSEX) 课程表:COURSE(C#,CNAME,T#) 成绩表:SC(S#,C ...

  6. 经典sql语句50题_SQL面试经典50题:带你从建表开始

    大家好,相信很多学习数据分析的小伙伴在面试前都经历过刷题,本系列小编将带大家一起来刷一刷SQL面试必会的经典50题. 当然本系列文章不单单是刷题,小编会带着大家梳理一下解题时用到的知识点,所以基础比较 ...

  7. SQL 高级查询 50题

    一个题目涉及到的50个Sql语句 --(下面表的结构以给出,自己在数据库中建立表.并且添加相应的数据,数据要全面些. 其中Student表中,SId为学生的ID) ------------------ ...

  8. sql查询文章上一篇下一篇

    遇到显示文章时显示上一篇.下一篇的id.title提示需求,经常就是取到当前文章,然后再根据发布时间分别取到上一篇.下一篇文章,然是这样要交互三次数据库,想写一个sql一次执行出来,原来写的是 SEL ...

  9. SQL经典50题(MySQL版)

    近段时间一直都在学习MySQL,为了检验自己的学习效果,特意拿了网上经典的SQL50题练了一下. 我用的是MySQL Server 8.0版本(新增了窗口函数rank()等,接下来我会把自己的SQL语 ...

最新文章

  1. 智慧城市新探索:摩拜京东联合利用智能单车数据检测违章停车
  2. Windows Phone本地数据库(SQLCE):11、使用LINQ查询数据库(翻译) (转)
  3. Springboot+Swagger
  4. mysql 读写引擎_揭秘MySQL存储引擎spider
  5. matlab字符和字符串,MATLAB字符和字符串
  6. C++ STL里的排序去重函数 超级方便
  7. Bootstrap表格表单
  8. MySQL高级知识(五)——索引分析
  9. 指定输出路径_新版Creo输入输出配置不用愁,果断收藏本文就对了
  10. 使用VS2010编译64的Geos库
  11. Note for Multi Agent Teamwork—A Survey
  12. JavaScript 取得当前页面的URL网址参数
  13. MkDocs安装、生成文档、风格配置、插件安装
  14. 文件系统功能 os模块 子模块os.path pickle
  15. PS 图片清晰度
  16. OpwnWrt 路由器MWAN3多线多拨实现方法
  17. ubuntu在终端会话和图形界面之间切换的快捷键
  18. 13. 中国古代数学家张丘建在他的《算经》中提出了一个著名的“百钱百鸡问题”:一只公鸡值5钱,一只母鸡值3钱,三只小鸡值1钱,现在要用百钱买百鸡,请问公鸡、母鸡、小鸡各多少只?
  19. 数据结构翻转课堂答疑实录——概述
  20. 重力感应贪吃蛇(C51 MPU6050 8*8LED点阵)

热门文章

  1. 使用互传APP实现Android手机投屏到windows电脑
  2. html 404错误页面模板,50款国外非常有意思的网页404错误页面模板
  3. pymongo 基本操作
  4. Altium desiger10安装破解过程
  5. springboot-vue前后端分离登录
  6. 如何使用SMS向客户传递服务信息?指南在这里!
  7. Docker下centos7镜像安装中文支持
  8. ES 检索 word、pdf 文档插件 ingest attachment 的管道配置和文档结构映射
  9. 淘宝“蓝鲸计划”细节内容曝光 收编谷歌中国资源
  10. 计算机术语写祝福语,祝福语精选