数据库学习1:数据库学习入门1-10题(基于MySQL)

工具

  本文所使用的工具是MySQL+Navicat for MySQL(for Mac),下载及安装可以参考网页上的文章。
在这里插入图片描述

MySQL环境配置

1.打开【终端】输入命令行:mysql -u root -p,看到【Enter password】输入:MySQL安装时设置的密码(Mac终端输入密码时,不会显示在页面上);
在这里插入图片描述 2. 密码输入后出现如下界面,说明已经在mysql内了:在这里插入图片描述
3.博主安装环境没有碰到太大问题,如果您在安装时碰到问题或者是想设置环境变量,请参看这篇帖子,写得非常好 :🔗https://www.jianshu.com/p/0e219ea23599

Navicat使用

1.打开左上角【连接】选择:“MySQL”,出现以下界面;在【连接名】输入:“localhost”,在【密码】输入:MySQL安装时设置的密码;点击【保存】;
在这里插入图片描述
2.左边栏为数据库,新建数据库方法1:右键【localhost】->【新建数据库】;新建数据库方法2:【工具】->【命令列界面】->输入:create database +(数据库名)
在这里插入图片描述
3.打开数据库,打开选中的数据库->打开【查询】->点击【新建查询】输入:建表语句。

SQL面试必会50题1

0.新建表:在新建查询中复制粘贴以下内容:

-- 建表
-- 学生表
CREATE TABLE `Student`(
`s_id` VARCHAR(20),
`s_name` VARCHAR(20) NOT NULL DEFAULT '',
`s_birth` VARCHAR(20) NOT NULL DEFAULT '',
`s_sex` VARCHAR(10) NOT NULL DEFAULT '',
PRIMARY KEY(`s_id`)
);
-- 课程表
CREATE TABLE `Course`(
`c_id` VARCHAR(20),
`c_name` VARCHAR(20) NOT NULL DEFAULT '',
`t_id` VARCHAR(20) NOT NULL,
PRIMARY KEY(`c_id`)
);
-- 教师表
CREATE TABLE `Teacher`(
`t_id` VARCHAR(20),
`t_name` VARCHAR(20) NOT NULL DEFAULT '',
PRIMARY KEY(`t_id`)
);
-- 成绩表
CREATE TABLE `Score`(
`s_id` VARCHAR(20),
`c_id` VARCHAR(20),
`s_score` INT(3),
PRIMARY KEY(`s_id`,`c_id`)
);
-- 插入学生表测试数据
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' , '女');
-- 课程表测试数据
insert into Course values('01' , '语文' , '02');
insert into Course values('02' , '数学' , '01');
insert into Course values('03' , '英语' , '03');

-- 教师表测试数据
insert into Teacher values('01' , '张三');
insert into Teacher values('02' , '李四');
insert into Teacher values('03' , '王五');

-- 成绩表测试数据
insert into Score values('01' , '01' , 80);
insert into Score values('01' , '02' , 90);
insert into Score values('01' , '03' , 99);
insert into Score values('02' , '01' , 70);
insert into Score values('02' , '02' , 60);
insert into Score values('02' , '03' , 80);
insert into Score values('03' , '01' , 80);
insert into Score values('03' , '02' , 80);
insert into Score values('03' , '03' , 80);
insert into Score values('04' , '01' , 50);
insert into Score values('04' , '02' , 30);
insert into Score values('04' , '03' , 20);
insert into Score values('05' , '01' , 76);
insert into Score values('05' , '02' , 87);
insert into Score values('06' , '01' , 31);
insert into Score values('06' , '03' , 34);
insert into Score values('07' , '02' , 89);
insert into Score values('07' , '03' , 98);

用一张图介绍4张表联结关系2
在这里插入图片描述

1.查询课程编号为“01”的课程比“02”的课程成绩高的所有学生的学号(重点)

原Score表如下:第一列是“学生学号”,第二列是“课程编号”,第三列是“对应分数”。
在这里插入图片描述
若想要查询课程编号为“01”的课程比“02”的课程成绩高的所有学生的学号,我们最希望先得到一张这样的表格:

idscore01score02
学号1课程01分数课程02分数

根据上表,查询伪代码可以写为:SELECT id FROM Score WHERE s_score01 > s_score01

SELECT a.s_id'学号',a.s_score'课程01分数',b.s_score'课程02分数' FROM 
-- 从a表和b表内联结得到的表中选择a.s_id,a.s_score,b.s_score并命名为'学号','课程01分数','课程02分数'
(
SELECT s_id,c_id,s_score FROM Score WHERE c_id = '01' -- 从Score表中选出c_id = ‘01’的行,将所有这些行并起来构成a表
) AS a
INNER JOIN -- inner join:内联结
(
SELECT s_id,c_id,s_score FROM Score WHERE c_id = '02'
) AS b ON a.s_id = b.s_id -- on + 内联结条件:“a表和b表学号相同”

得到如下结果,也就是我们理想的表:
在这里插入图片描述
在上面的代码后补充语句:

WHERE a.s_score > b.s_score

在这里插入图片描述
得到本题答案,学号02和04的学生课程01分数比02高。

补充:从Student表中,查询课程01比课程02分数高的学生姓名。

先查看Student表:
在这里插入图片描述
即再内联结Student表,在所有联结起来的表中再选上s_name。

SELECT a.s_id'学号',c.s_name'姓名',a.s_score'课程01分数',b.s_score'课程02分数' FROM

(
SELECT s_id,c_id,s_score FROM Score WHERE c_id = '01'
) AS a
INNER JOIN
(
SELECT s_id,c_id,s_score FROM Score WHERE c_id = '02'
) AS b ON a.s_id = b.s_id
INNER JOIN
Student AS c ON c.s_id = a.s_id -- as 设置表名

WHERE a.s_score > b.s_score

在这里插入图片描述

2.查询平均成绩大于60分的学生的学号和平均成绩(简单,第二道重点)

查看Score表。
在这里插入图片描述
若想要查询平均成绩大于60分的学生的学号和平均成绩,我们最希望先得到一张这样的表格:

idaverage
学号1平均分分数

将Score表根据s_id分类,

SELECT s_id'学号',AVG(s_score)'平均分'
	FROM Score
GROUP BY s_id HAVING AVG(s_score) > 60

GROUP BY中的条件不用WHERE,而用HAVING + 选择条件

在这里插入图片描述

3.查询所有学生的学号、姓名、选课数、总成绩(不重要)

若想要查询所有学生的学号、姓名、选课数、总成绩,我们最希望先得到一张这样的表格:

学号姓名课程编号这门课的成绩
1小张160
1小张250
2小李175
2小李280

把Student表和Score表联结在一起,我们此处选择左联结left join。

SELECT * 
FROM Student AS a
LEFT JOIN Score AS b ON a.s_id = b.s_id

内联结:例如以s_id内联结,则会选择两表学号的交集进行联结。例如Student表中有01~08号学生,但08号学生没有考试成绩,故Score表中仅有01~07号学生,内联结后取交集便是01~07号学生的个人信息和成绩。
在这里插入图片描述
左联结:例如以s_id左联结,则会选择LEFT JOIN语句前的表的学号作为新表的学号。例如Student表中有01~08号学生,Score表中仅有01~07号学生,内联结后便以前表的学号为准,便是01~08号学生的个人信息和成绩(无成绩的学生课程栏和成绩栏以NULL填充)。
在这里插入图片描述
右联结:例如以s_id右联结,则会选择RIGHT JOIN语句后的表的学号作为新表的学号。例如Student表中有01~08号学生,Score表中仅有01~07号学生,内联结后便以后表的学号为准,便是01~07号学生的个人信息和成绩;如果Student表中有02~08号学生,Score表中仅有01~07号学生,内联结后还是以后表的学号为准,便是01~07号学生的个人信息和成绩。
在这里插入图片描述
全联结:MySQL是不支持full join的,但仍然可以同过 a LEFT JOIN b + UNION + a RIGHT JOIN b 实现。这样无论a,b两表学号是怎么样的,全联结得到的表学号包含了a,b两表中所有的学号。

将左联结后的表中不同学号的人通过group by函数分类,选课数通过count函数计数,总成绩通过sum函数计算。

SELECT a.s_id,a.s_name,COUNT(b.c_id),SUM(b.s_score) 
FROM Student AS a
LEFT JOIN 
Score AS b ON a.s_id = b.s_id
GROUP BY s_id,s_name 

经GROUP BY函数分类后,原则上,SELECT函数只能选择GROUP BY函数后跟的列名以及统计项(例如COUNT、SUM函数)。

在这里插入图片描述
补充:将王菊的总成绩从NULL改为一般我们使用的“0”。

SELECT a.s_id,a.s_name,COUNT(b.c_id)'选课数',
SUM(CASE WHEN b.s_score IS NULL THEN 0 ELSE b.s_score END)'总成绩'
FROM Student AS a
LEFT JOIN Score AS b ON a.s_id = b.s_id
GROUP BY s_id,s_name

CASE WHEN结构3如下:
CASE case_value
WHEN when_value THEN
statement_list
WHEN when_value THEN
statement_list
ELSE
statement_list
END CASE;

注意⚠️:需要注意的是,如果两个条件都针对一个字段的话,会显示第一个when的值。
CASE WHEN是一个非常好的结构,面试加分项。

在这里插入图片描述

4.查询姓“猴”的老师的个数(不重要)

SELECT COUNT(t_id)
FROM Teacher
WHERE t_name LIKE '猴%'

LIKE通常与通配符%一起使用,%表示通配pattern中出现的内容,例如此处的通配pattern为“猴”;而不加通配符%的LIKE语法,表示精确匹配,其实际效果等同于“= 运算符”。

在这里插入图片描述
补充:查询姓“张”的老师的个数和姓名含“张”的老师的个数。

SELECT COUNT(t_name)
FROM Teacher
WHERE t_name LIKE '张%' -- 名字开头是“张”

在这里插入图片描述

一般情况下,表格可能有统一姓名多次重复,可以用DISTINCT函数做去重复的工作。

SELECT COUNT(DISTINCT t_name) -- DISTINCT 去重复
FROM Teacher
WHERE t_name LIKE '张%' -- 名字开头是“张”

在这里插入图片描述

SELECT COUNT(t_id)
FROM Teacher
WHERE t_name LIKE '%张%' -- 名字包含“张”

通配符%用法:’%张%'代表查询含“张”的字符串,'张%'代表查询开头字符为“张”的字符串。

在这里插入图片描述

5.查询没学过“张三”老师课的学生的学号、姓名(重点)

最开始的想法💡:先查询学过“张三”老师课的学生的学号,再找“补集”。

法一

步骤:从Teacher表中根据姓名t_name“张三”查询教师编号t_id
→ \rightarrow 到Course表中根据t_id查询对应的课程编号c_id
→ \rightarrow 到Score表中根据c_id查询对应的学生学号s_id,“张三”老师课程有分数的被认为选了课
→ \rightarrow 以上构造出了学过“张三”老师课的学生学号的表,到Student表中查询不在上述学号中的同学学号及姓名

查询学过“张三”老师课的学生的学号:

SELECT s_id FROM Score
WHERE c_id =
	(
	SELECT c_id FROM Course
	WHERE t_id =
		(
		SELECT t_id FROM Teacher
		WHERE t_name = '张三'
		)
	)

此处一定要注意,WHERE c_id = SELECT 后面一定要精确到查询出c_id,不能多查询出其他列,不然无法一一对应。

在这里插入图片描述

查询没学过“张三”老师课的学生的学号、姓名:

SELECT s_id'学号',s_name'姓名' FROM Student
WHERE s_id NOT IN
(	
SELECT s_id FROM Score
WHERE c_id =
	(
	SELECT c_id FROM Course
	WHERE t_id =
		(
		SELECT t_id FROM Teacher
		WHERE t_name = '张三'
		)
	)
)

IN函数后面加取值区间。

在这里插入图片描述

经典错误写法

SELECT * FROM Score
WHERE c_id != '02'

如果直接从Score表中找课程编号不等于“张三”老师课的学生学号,会出现以下问题:
在这里插入图片描述

因为Score表中是把一个学号拆开来分别对应每个课程建立的,所以选择c_id不等于“02”的学号,是把一个学号下的一条信息删除了,依然保留了该学号c_id等于“01”“03”课的成绩,即这个学号还是会被认为没选“张三”老师的课。

法二
考虑构造如下图表:

学号课程编号成绩教师编号教师姓名

这样就可以一下子查询到学过“张三”老师课的学生学号。

SELECT s_id,s_name FROM Student
WHERE s_id NOT IN
(
SELECT s_id
FROM Score AS s
INNER JOIN Course AS c ON s.c_id = c.c_id
INNER JOIN Teacher AS t ON c.t_id = t.t_id
WHERE t.t_name = '张三'
)

6.查询学过“张三”老师所教的所有课的同学的学号、姓名(重点)

此题和5.无独有偶。

7.查询学过编号为“01”的课程并且也学过编号为“02”的课程的学生的学号、姓名(重点)

经典错误写法

SELECT * FROM Score
WHERE c_id = '01' and c_id = '02'

在Score表中c_id这项既等于‘01’又等于‘02’是不可能的,故取出来的只会是空集。
在这里插入图片描述
正确的想法——我们应该考虑建立以下两张表,再构造内联结取两表信息交集:

学过课程01 的学生学号
1
2
3
4
5
6
学过课程02 的学生学号
1
2
3
4
5
7
SELECT a.s_id FROM
(SELECT s_id FROM Score WHERE c_id = '01') AS a
INNER JOIN
(SELECT s_id FROM Score WHERE c_id = '02') AS b
ON a.s_id = b.s_id

在这里插入图片描述

8.查询课程编号为“02”的总成绩(不重点)

法一

SELECT SUM(s_score)'sum',AVG(s_score)'avg',COUNT(s_score)'count',COUNT(DISTINCT s_id)'count1' 
FROM Score
WHERE c_id = '02'

在这里插入图片描述

法二
先考虑建立每一门课程的总成绩/平均分/选修人数表,再从中选出程编号为“02”的。

SELECT c_id,SUM(s_score)'sum',AVG(s_score)'avg',COUNT(s_score)'count',COUNT(DISTINCT s_id)'count1' 
FROM Score
GROUP BY c_id

在这里插入图片描述

SELECT c_id,SUM(s_score)'sum',AVG(s_score)'avg',COUNT(s_score)'count',COUNT(DISTINCT s_id)'count1' 
FROM Score
GROUP BY c_id HAVING c_id = '02'

9.查询所有课程成绩小于60分的学生的学号、姓名(知乎小番茄的资料里写的不对)

步骤:先得出同学成绩小于60分的课程数 → \rightarrow 统计同学总共学了几门课 → \rightarrow 两数相同,则满足查询条件

SELECT a.s_id,c.s_name
FROM
(
SELECT s_id,COUNT(c_id) AS cnt FROM Score -- AS cnt改成'cnt'也可以
WHERE s_score < 60
GROUP BY s_id
) AS a
INNER JOIN
(
SELECT s_id,COUNT(c_id) AS cnt FROM Score
GROUP BY s_id
) AS b 
ON a.s_id = b.s_id
INNER JOIN Student AS c 
ON a.s_id = c.s_id 

WHERE a.cnt = b.cnt

在这里插入图片描述

10.查询没有学全所有课的学生的学号、姓名(重点)

易错点:要小心一门课都没选的同学!!故要使用LEFT JOIN把学号多的那张表放在前面!!

步骤:先找出总共课程数目
→ \rightarrow 将Student表和Score表进行左联结,得到一张具有完整的学生信息和成绩的表
→ \rightarrow 在该表中对学号分类,分类后以选课数小于总课数作为条件进行查询

先找出总共课程数目:

SELECT COUNT(DISTINCT c_id) FROM Course

Student表和Score表进行左联结,得到一张具有完整的学生信息和成绩的表:

SELECT * FROM 
Student AS a
LEFT JOIN 
Score AS b ON a.s_id = b.s_id

得到最终结果:

SELECT a.s_id,a.s_name
FROM 
Student AS a
LEFT JOIN 
Score AS b ON a.s_id = b.s_id
GROUP BY s_id 
HAVING COUNT(DISTINCT c_id) < 
	   (SELECT COUNT(DISTINCT c_id) FROM Course)

在这里插入图片描述

一点补充

1.NULL长度

SELECT LENGTH(NULL)

结果:
在这里插入图片描述

学习依托资料

  1. B站视频专栏-up主:陆小亮-【数据分析】- SQL面试50题 - 跟我一起打怪升级 一起成为数据科学家;
  2. 知乎-猴子-常见的SQL面试题:经典50题https://zhuanlan.zhihu.com/p/38354000
  3. 知乎-小番茄-SQL面试必会50题https://zhuanlan.zhihu.com/p/43289968

  1. 知乎-小番茄-SQL面试必会50题https://zhuanlan.zhihu.com/p/43289968 ↩︎

  2. 知乎-猴子-常见的SQL面试题:经典50题https://zhuanlan.zhihu.com/p/38354000 ↩︎

  3. 博客园-马踏飞燕Beautiful-mysql case when then else end 用法经验总结
    https://www.cnblogs.com/Formulate0303/p/11962254.html ↩︎

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQL查询二 2 通过本实验使学生掌握多表查询子查询以及基本数据操作 二、实验内容 使用实验一建立的银行贷款数据库和表,完成以下查询。 1-4是多表查询子查询,5-11是数据操作 查询经济性质为“国营”的法人在上海的银行贷款的信息,列出法人代码、银行代码和贷款日期,分别用多表连接和子查询两种方式实现。 查询在“建设银行上海分行”贷过款的法人名称,分别用多表连接和子查询两种方式实现。 查询在“工商银行北京A支行”贷款金额前名(包括并列的情况)的法人的法人代码、法人名称和经济性质,分别用多表连接和子查询两种方式实现。 查询在“工商银行北京B支行”贷款、且贷款金额高于此银行的平均贷款金额的法人代码、贷款日期和贷款金额。 在银行表中插入如下数据:银行代码号为:B321B,银行名称为:建设银行上海B分行,电话为空值。 在法人表中插入如下数据:法人代码号为:E11,法人名称为:新法人,注册资金为:2350万元,经济性质使用默认值。 删除银行编号为“B321B”的银行信息。 删除2000年之前一次贷款金额最小的贷款记录。 删除从贷款日期到当前日期天数超过10年的贷款记录。 删除法人名称为“爱贝乐玩具有限公司”且贷款金额小于10万元的贷款记录,分别用子查询和多表连接两种方式实现。 将经济性质为“私营”的法人在“工商银行上海支行”贷款的所有贷款金额加5万元,分别用子查询和多表连接两种方式实现。 使用实验一建立的学生数据库和表,完成以下查询 12-15是多表查询子查询,16-20是数据操作 查询计算机系年龄大于总平均年龄的学生的姓名和年龄。 查询计算机系年龄大于计算机系平均年龄的学生的姓名和年龄。 查询计算机系考试成绩小于总平均分的学生的学号、姓名。 将考试成绩最低的并且不及格学生的最低修成绩改为60。 将数据库基础考试成绩最低的且成绩为不及格学生的数据库考试成绩改为60。 删除计算机系“计算机网络”程的全部选记录。 删除vb考试成绩最低的两个学生的vb考试记录。 对数据库考试成绩进行如下修改:如果成绩低于60分,则提高10%;如果成绩在60到80之间,则增加6%;如果成绩在80到95之间则提高4%,其他情况不提高。 对学分进行如下修改:如果是第1到第3学期开始的程,则学分增加1分;如果是第4到第6学期开设的程,学分增加2分,其他学期开始的程学分增加3分。 以下查询必须用子查询完成: 查询男生年龄最大的学生的姓名和所在系。 查询选修了‘数据库基础’的学生的姓名、所在系。s 选修了第6学期开始的程的学生的学号、姓名和所在系。 查询男生所修的程的程名。 查询年龄最小的学生所选的程名。 、实验报告 将实验结果反映在实验报告中,并对实验中遇到的问及解决方案、进行整理、分析总结,提出实验结论或自己的看法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值