SQL笔试经典50题及答案解析(题目11-20)

前言
最近博主在准备数据分析岗位的笔试和面试,其中的考察重点就是SQL。听说练了这50道题目(题目和数据来源参考:互联网校招SQL笔试经典50题及答案解析),什么现场手撕SQL统统都不怕,我就赶紧来练习了!壮士们,练完以后就什么都不怕啦~

我看了原博主的查询语句,有些不够简洁,有些或许存在问题。下面都是我自己写的查询语句,保证在Navicat上跑得通,但是不排除存在写的不对不好的地方,欢迎大家提出来,一起学习,共同进步。

环境:
Navicat Premium 12

说明:
本篇练习的是题目11-20,都很简单,新手也不用害怕~
其余题目请参考链接:
SQL笔试经典50题及答案解析(题目1-10)
SQL笔试经典50题及答案解析(题目21-30)
SQL笔试经典50题及答案解析(题目31-40)
SQL笔试经典50题及答案解析(题目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  # 最后把有两门及以上不及格的人过滤出来

注意事项

运行结果
在这里插入图片描述

题目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

注意事项

运行结果
在这里插入图片描述

题目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

注意事项

运行结果
在这里插入图片描述

发布了8 篇原创文章 · 获赞 2 · 访问量 538

猜你喜欢

转载自blog.csdn.net/weixin_43890183/article/details/104905414
今日推荐