SQL笔试经典50题及答案解析(题目11-20)
前言
最近博主在准备数据分析岗位的笔试和面试,其中的考察重点就是SQL。听说练了这50道题目,什么现场手撕SQL统统都不怕,我就赶紧来练习了!壮士们,练完以后就什么都不怕啦~
环境:
Navicat Premium 12
说明:
本篇练习的是题目11-20,都很简单,新手也不用害怕~
题目1-10:
题目21-30:
题目31-40:
题目41-50:
创建表
表说明
本次创建的表有四张:
- 学生表(student): 包含 学生号,学生姓名,出生年月,性别 四个字段
- 教师表(teacher): 包含教师号,教师姓名 两个字段
- 成绩表(sc): 包含学生号,课程号,成绩 三个字段
- 课程表(course): 包含课程号,课程名,教师号 三个字段
表创建
# 创建学生表
create table Student(sid varchar(10),sname varchar(10),sage datetime,ssex nvarchar(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 decimal(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);
表显示
学生表如下:
教师表如下:
成绩表如下:
课程表如下:
题目
题目11
查询至少有一门课与学号为“01”的同学所学相同的同学的学号和姓名;
SELECT DISTINCT sc.sid,sname
FROM sc
JOIN student AS s
ON sc.sid = s.sid
WHERE cid IN
# 只要其他同学的cid包含在“01”同学的课程里面,就满足至少修了一门一样的课程,这里使用IN就行
(
SELECT DISTINCT cid
FROM sc
WHERE sid='01'
)# 找出“01”同学都学了哪些课程,为了避免有些课程有多个成绩(重修),因此这里在cid前面加上DISTINCT
注意事项:
- 考察IN的用法:其实就是在一群值里面搜索
运行结果:
题目12(重要)
查询和"01"号的同学学习的课程完全相同的其他同学的学号和姓名
SELECT DISTINCT sc.sid,sname
FROM sc
JOIN student AS s
ON sc.sid = s.sid
WHERE sc.sid!= '01' # 查询和01同学一样的,把01同学本人在名单里面排除
AND cid IN
(
SELECT DISTINCT cid
FROM sc
WHERE sid='01'
) # 课程内容:在01同学所学课程范围内(排除学了其他课程的同学)
GROUP BY sc.sid
HAVING COUNT(DISTINCT sc.cid)
=(SELECT COUNT(DISTINCT cid) FROM sc WHERE sid='01') # 课程数量:也要和01同学一样
注意事项:
- 完全相同,意味着既要课程数量相同,又要课程内容相同
运行结果:
题目13(重要)
把“SC”表中“张三”老师教的课的成绩都更改为此课程的平均成绩;
UPDATE sc
SET score=
(
SELECT avg_score FROM
# 不加这一层会报错:错误提示会说,不能先select出同一表中的某些值,再update这个表(在同一语句中)
# 解决办法:update的时候注意加上这一层查询就能解决问题了,下面同理
(
SELECT AVG(score) AS avg_score
FROM sc
LEFT JOIN course AS c ON sc.cid = c.cid
LEFT JOIN teacher AS t ON c.tid = t.tid
WHERE t.tname = '张三' # 查询张三老师教的课程的平均成绩
) AS t1
)
WHERE cid IN(
SELECT cid FROM
(
SELECT DISTINCT sc.cid FROM sc
LEFT JOIN course AS c ON sc.cid = c.cid
LEFT JOIN teacher AS t ON c.tid = t.tid
WHERE t.tname = '张三'
) AS t2
)
注意事项:
- UPDATE用法:UPDATE 表名称 SET 列名称 = 新值 [WHERE 列名称 = 某值](方括号里面的语句表示可选)
-
解题思路:
- 先算出“张三”老师教的课的成绩的平均成绩
- 进行update的时候,使用where限定课程教师是张三
运行结果:
有6行记录被改变了,接下来让我们详细看一下原始数据表:
题目14
查询没学过"张三"老师讲授的任一门课程的学生姓名
SELECT DISTINCT sid,sname
FROM student
WHERE sid NOT IN
(SELECT sid
FROM sc
LEFT JOIN course AS c ON sc.cid = c.cid
LEFT JOIN teacher AS t ON c.tid = t.tid
WHERE t.tname = '张三')
注意事项:
- 没学过张三老师的课,可以逆向思维进行思考,先选出修过张三老师课程的学生,然后使用NOT IN就可以排除这些学生了
运行结果:
题目15
查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
SELECT sc.sid,s.sname,AVG(score) AS avg_score
FROM sc
LEFT JOIN student AS s
ON sc.sid = s.sid
WHERE score<60 # 首先用where把所有不及格的成绩揪出来
GROUP BY sid # 然后按照学号进行分组
HAVING COUNT(DISTINCT score)>=2 # 最后把有两门及以上不及格的人过滤出来
注意事项:
- 注意逻辑:这道题目完美的考察了SQL关键词的先后执行顺序,一定记住了,是WHERE > GROUP BY > HAVING > ORDER BY
- 知识点:关于sql和MySQL的语句执行顺序(必看!!!)
运行结果:
题目16
检索"01"课程分数小于60,按分数降序排列的学生信息
SELECT sid,cid,score
FROM sc
WHERE cid='01' AND score < 60
ORDER BY score DESC
运行结果:
题目17
按平均成绩从高到低显示所有学生的平均成绩
SELECT sid,AVG(score) AS avg_score
FROM sc
GROUP BY sid # 按照学号归类,求成绩均值
ORDER BY avg_score desc
运行结果:
题目18
查询各科成绩最高分、最低分和平均分:以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率
方法1:使用sum计数
# 方法1
SELECT
sc.cid
,c.cname
,MAX(score)
,MIN(score)
,AVG(score)
,sum(IF(score>=60,1,0))/COUNT(score) AS pass_rate #分数大于60记为1,否则记为0,然后求和
FROM sc
LEFT JOIN course AS c ON sc.cid = c.cid
GROUP BY cid
方法2:使用count计数
# 方法2
SELECT
sc.cid
,c.cname
,MAX(score)
,MIN(score)
,AVG(score)
,COUNT(IF(score>=60,score,NULL))/COUNT(score) AS pass_rate #分数大于60返回score,否则返回null,然后计数
FROM sc
LEFT JOIN course AS c ON sc.cid = c.cid
GROUP BY cid
注意事项:
- 这里用了函数嵌套,需要注意一下,理解了就很简单
- 知识点:IF( expr1 , expr2 , expr3 ) sql中的 IF 条件语句的用法
运行结果:
题目19
按各科平均成绩从低到高和及格率的百分数从高到低顺序
SELECT
sc.cid
,AVG(score)AS avg_score
,sum(IF(score>=60,1,0))/COUNT(score) AS pass_rate
FROM sc
GROUP BY cid
ORDER BY avg_score ASC,pass_rate DESC # 先按照平均成绩升序排,再按照及格率降序排
注意事项:
- ORDER BY使用的时候,可以按照多个字段进行排序,中间用逗号隔开
运行结果:
题目20(重要)
查询学生的总成绩并进行排名
方法1:使用自连接
# 方法1
#核心思想:>=60分的有三个,那么60就是第3名;>=某数的值有几个,某数就排第几名
SELECT t1.sid,t1.total_score,COUNT(t2.total_score) AS srank #此处别名不要用rank,会报错
FROM
(SELECT sid,SUM(score) AS total_score
FROM sc
GROUP BY sid) AS t1 #创建表1,按照学号分组,计算每个学生总分
LEFT JOIN
(SELECT sid,SUM(score) AS total_score
FROM sc
GROUP BY sid) AS t2 #创建表2,和表1一模一样
ON t1.total_score<=t2.total_score
#关键操作!记住这个连接条件,对于表1的每一行,在表2中的数据都存在所有>=表1的数据;
GROUP BY t1.total_score
# 然后按照表1的成绩进行分组,对表2的数据计数,这就是排名
ORDER BY t1.total_score DESC
方法2:使用函数rank()
# 方法2
SELECT
sid
,SUM(score) AS total_score
,rank() over (ORDER BY SUM(score) DESC) AS srank
FROM sc
GROUP BY sid
注意事项:
- 方法1: 核心思想:>=60分的有三个,那么60就是第3名;>=某数的值有几个,某数就排第几名。一定牢牢记住,使用自连接可以得到排名!很好用的方法~
- 方法2: 知识点:sql 四大排名函数 — ROW_NUMBER、RANK、DENSE_RANK、NTILE
运行结果:
上一篇: 关于数据库查询
下一篇: 【C++】类与对象(二)