更正文档中的问题和笔误

pull/43/head
jackfrued 2023-02-06 00:54:41 +08:00
parent 558049fd0d
commit 965af7c53f
50 changed files with 390 additions and 345 deletions

0
.gitignore vendored 100644 → 100755
View File

0
README.md 100644 → 100755
View File

0
第01课:初识Python.md 100644 → 100755
View File

View File

View File

View File

0
第05课:分支结构.md 100644 → 100755
View File

0
第06课:循环结构.md 100644 → 100755
View File

View File

View File

View File

View File

View File

View File

0
第13课:函数和模块.md 100644 → 100755
View File

0
第14课:函数的应用.md 100644 → 100755
View File

0
第15课:函数使用进阶.md 100644 → 100755
View File

View File

View File

View File

View File

@ -1,4 +1,4 @@
## 第18课:面向对象编程应用
## 第19课:面向对象编程应用
面向对象编程对初学者来说不难理解但很难应用,虽然我们为大家总结过面向对象的三步走方法(定义类、创建对象、给对象发消息),但是说起来容易做起来难。**大量的编程练习**和**阅读优质的代码**可能是这个阶段最能够帮助到大家的两件事情。接下来我们还是通过经典的案例来剖析面向对象编程的知识同时也通过这些案例为大家讲解如何运用之前学过的Python知识。

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

2
第41课.SQL详解之DDL.md 100644 → 100755
View File

@ -1,4 +1,4 @@
## SQL详解之DDL
## 第41课SQL详解之DDL
我们通常可以将 SQL 分为四类,分别是 DDL数据定义语言、DML数据操作语言、DQL数据查询语言和 DCL数据控制语言。DDL 主要用于创建、删除、修改数据库中的对象,比如创建、删除和修改二维表,核心的关键字包括`create`、`drop`和`alter`DML 主要负责数据的插入、删除和更新,关键词包括`insert`、`delete`和`update`DQL 负责数据查询,最重要的一个关键词是`select`DCL 通常用于授予和召回权限,核心关键词是`grant`和`revoke`。

2
第42课.SQL详解之DML.md 100644 → 100755
View File

@ -1,4 +1,4 @@
## SQL详解之DML
## 第42课SQL详解之DML
我们接着上一课中创建的学校选课系统数据库,为大家讲解 DML 的使用。DML 可以帮助将数据插入到二维表(`insert`操作)、从二维表删除数据(`delete`操作)以及更新二维表的数据(`update`操作)。在执行 DML 之前,我们先通过下面的`use`命令切换到`school`数据库。

507
第43课.SQL详解之DQL.md 100644 → 100755
View File

@ -1,370 +1,415 @@
## SQL详解之DQL
## 第43课SQL详解之DQL
接下来,我们利用之前创建的学校选课系统数据库,为大家讲解 DQL 的应用。无论对于开发人员还是数据分析师DQL 都是非常重要的,它关系着我们能否从关系数据库中获取我们需要的数据。建议大家把上上一节课中建库建表的 DDL 以及 上一节课中插入数据的 DML 重新执行一次,确保表和数据跟没有问题再执行下面的操作。
```SQL
use `school`;
-- 查询所有学生的所有信息
-- 说明:实际工作中不建议使用 select * 的方式进行查询
-- 01. 查询所有学生的所有信息
select *
from tb_student;
-- 查询学生的学号、姓名和籍贯
select stu_id,
stu_name,
stu_addr
select stu_id
, stu_name
, stu_sex
, stu_birth
, stu_addr
, col_id
from tb_student;
select stu_id as 学号,
stu_name as 姓名,
stu_addr as 籍贯
-- 02. 查询学生的学号、姓名和籍贯(投影和别名)
select stu_id as 学号
, stu_name as 姓名
, stu_addr as 籍贯
from tb_student;
-- 查询所有课程的名称及学分
select cou_name as 课程名称,
cou_credit as 学分
-- 03. 查询所有课程的名称及学分(投影和别名)
select cou_name as 课程名称
, cou_credit as 学分
from tb_course;
-- 查询所有女学生的姓名和出生日期
select stu_name,
stu_birth
-- 04. 查询所有女学生的姓名和出生日期(数据筛选)
select stu_name
, stu_birth
from tb_student
where stu_sex=0;
where stu_sex = 0;
-- 查询籍贯为“四川成都”的女学生的姓名和出生日期
select stu_name,
stu_birth
-- 05. 查询籍贯为“四川成都”的女学生的姓名和出生日期(数据筛选)
select stu_name
, stu_birth
from tb_student
where stu_sex=0
and stu_addr='四川成都';
where stu_sex = 0 and stu_addr = '四川成都';
-- 查询籍贯为“四川成都”或者性别是女的学生
select stu_name,
stu_birth
-- 06. 查询籍贯为“四川成都”或者性别是女的学生(数据筛选)
select stu_name
, stu_birth
from tb_student
where stu_sex=0
or stu_addr='四川成都';
where stu_sex = 0 or stu_addr = '四川成都';
-- 查询所有80后学生的姓名、性别和出生日期
-- 方法一:
select stu_name,
stu_sex,
stu_birth
-- 07. 查询所有80后学生的姓名、性别和出生日期(数据筛选)
select stu_name
, stu_sex
, stu_birth
from tb_student
where stu_birth >= '1980-1-1'
and stu_birth <= '1989-12-31';
where '1980-1-1' <= stu_birth and stu_birth <= '1989-12-31';
-- 方法二:
select stu_name,
stu_sex,
stu_birth
select stu_name
, stu_sex
, stu_birth
from tb_student
where stu_birth between '1980-1-1' and '1989-12-31';
-- 查询学分大于2的课程的名称和学分
select cou_name,
cou_credit
-- MySQL方言
select stu_name
, if(stu_sex, '男', '女') as stu_sex
, stu_birth
from tb_student
where stu_birth between '1980-1-1' and '1989-12-31';
select stu_name
, case stu_sex
when 1 then '男'
else '女'
end as stu_sex
, stu_birth
from tb_student
where stu_birth between '1980-1-1' and '1989-12-31';
-- 08. 查询学分大于2分的课程名称和学分(数据筛选)
select cou_name
, cou_credit
from tb_course
where cou_credit > 2;
-- 查询学分是奇数的课程的名称和学分
select cou_name,
cou_credit
-- 09. 查询学分是奇数的课程的名称和学分(数据筛选)
select cou_name
, cou_credit
from tb_course
where cou_credit % 2 <> 0;
where cou_credit mod 2 <> 0;
-- 查询选择选了1111的课程考试成绩在90分以上的学生学号
-- 10. 查询选择选了1111的课程考试成绩在90分以上的学生学号(数据筛选)
select stu_id
from tb_record
where cou_id = 1111
and score > 90;
where cou_id = 1111 and score > 90;
-- 查询姓“杨”的学生姓名和性别(模糊)
-- % 可以匹配零个或任意多个字符
select stu_name,
stu_sex
-- 11. 查询名字叫“杨过”的学生的姓名和性别
select stu_name
, stu_sex
from tb_student
where stu_name = '杨过';
-- 12. 查询姓“杨”的学生姓名和性别(模糊查询)
-- wild card - 通配符 - % - 代表零个或任意多个字符
select stu_name
, stu_sex
from tb_student
where stu_name like '杨%';
-- 查询姓“杨”名字两个字的学生姓名和性别(模糊)
-- _ 可以匹配一个字符
select stu_name,
stu_sex
-- 13. 查询姓“杨”名字两个字的学生姓名和性别(模糊查询)
-- wild card - 通配符 - _ - 精确匹配一个字符
select stu_name
, stu_sex
from tb_student
where stu_name like '杨_';
-- 查询姓“杨”名字三个字的学生姓名和性别(模糊)
select stu_name,
stu_sex
-- 14. 查询姓“杨”名字三个字的学生姓名和性别(模糊查询)
select stu_name
, stu_sex
from tb_student
where stu_name like '杨__';
-- 查询名字中有“不”字或“嫣”字的学生的姓名(模糊)
-- 方法一:
select stu_name,
stu_sex
-- 15. 查询名字中有“不”字或“嫣”字的学生的姓名(模糊查询)
select stu_name
from tb_student
where stu_name like '%不%'
or stu_name like '%嫣%';
where stu_name like '%不%' or stu_name like '%嫣%';
-- 方法二:
select stu_name,
stu_sex
select stu_name
from tb_student
where stu_name like '%不%'
union
select stu_name,
stu_sex
select stu_name
from tb_student
where stu_name like '%嫣%';
-- 查询姓“杨”或姓“林”名字三个字的学生的姓名
select stu_name,
stu_sex
from tb_student
where stu_name regexp '^[杨林][\\u4e00-\\u9fa5]{2}$';
update tb_student
set stu_name = '岳不嫣'
where stu_id = 1572;
-- 查询没有录入籍贯的学生姓名
select stu_name
from tb_student
where stu_addr = ''
or stu_addr is null;
-- 查询录入了籍贯的学生姓名
where stu_name like '%不%'
union all
select stu_name
from tb_student
where stu_addr <> ''
and stu_addr is not null;
where stu_name like '%嫣%';
-- 查询学生选课的所有日期
-- 16. 查询姓“杨”或姓“林”名字三个字的学生的姓名(正则表达式模糊查询)
-- regular expression
select stu_name
from tb_student
where stu_name regexp '[杨林][\\u4e00-\\u9fa5]{2}';
-- 17. 查询没有录入籍贯的学生姓名(空值处理)
select stu_name
from tb_student
where stu_addr is null or trim(stu_addr) = '';
update tb_student
set stu_addr = ' '
where stu_id = 1572;
-- 18. 查询录入了籍贯的学生姓名(空值处理)
select stu_name
from tb_student
where stu_addr is not null and trim(stu_addr) <> '';
-- 19. 查询学生选课的所有日期(去重)
select distinct sel_date
from tb_record;
-- 查询学生的籍贯
-- 20. 查询学生的籍贯(空值处理和去重)
select distinct stu_addr
from tb_student
where stu_addr <> ''
and stu_addr is not null;
where stu_addr is not null and trim(stu_addr) <> '';
-- 查询学院编号为1的学生姓名、性别和生日按年龄从大到小排列
-- asc - 升序从小到大默认desc - 降序(从大到小)
select stu_name,
stu_sex,
stu_birth
-- 21. 查询男学生的姓名和生日按年龄从大到小排列(排序)
-- ascending / descending
select stu_name
, stu_birth
from tb_student
where col_id = 1
order by stu_sex asc,
stu_birth asc;
where stu_sex = 1
order by stu_birth asc;
-- 补充:将上面的性别处理成“男”或“女”,将生日换算成年龄
select stu_name as 姓名,
if(stu_sex, '男', '女') as 性别,
floor(datediff(curdate(), stu_birth) / 365) as 年龄
-- 22. 将上面查询中的生日换算成年龄(日期函数、数值函数)
-- 获取当前日期curdate()
-- 计算时间差timestampdiff(unit, date1, date2)
select stu_name
, timestampdiff(year, stu_birth, curdate()) as stu_age
from tb_student
where col_id = 1
order by stu_sex asc,
年龄 desc;
where stu_sex = 1
order by stu_age desc;
-- 查询年龄最大的学生的出生日期
-- 聚合函数max / min / avg / sum / count / std / variance
-- 聚合函数会自动忽略掉null
-- 23. 查询年龄最大的学生的出生日期(聚合函数)
select min(stu_birth)
from tb_student;
-- 查询年龄最小的学生的出生日期
-- 24. 查询年龄最小的学生的出生日期(聚合函数)
select max(stu_birth)
from tb_student;
-- 查询学号为1001的学生一共选了几门课
select count(*)
-- 25. 查询编号为1111的课程考试成绩的最高分(聚合函数)
select max(score)
from tb_record
where cou_id = 1111;
-- 26. 查询学号为1001的学生考试成绩的最低分(聚合函数)
select min(score)
from tb_record
where stu_id = 1001;
-- 查询学号为1001的学生考试成绩的平均分
select round(avg(score), 1) as 平均分
-- 27. 查询学号为1001的学生考试成绩的平均分和标准差(聚合函数)
-- 四舍五入函数round(num, n)
select round(avg(score), 1) as avg_score
, round(std(score), 4) as std_score
from tb_record
where stu_id = 1001;
-- 查询学号为1001的学生考试成绩的平均分如果有null值null值算0分
-- 方法一:
-- 28. 查询学号为1001的学生考试成绩的平均分如果有null值null值算0分(聚合函数)
select sum(score) / count(*)
from tb_record
where stu_id = 1001;
-- 方法二:
select avg(coalesce(score, 0))
from tb_record
where stu_id = 1001;
-- 查询学号为1001的学生考试成绩的标准差(聚合函数)
select stddev_samp(score)
from tb_record
where stu_id = 1001;
-- 查询男女学生的人数
select case stu_sex when 1 then '男' else '女' end as 性别,
count(*) as 人数
-- 29. 查询男女学生的人数(分组和聚合函数)
select case stu_sex when 1 then '男' else '女' end as stu_sex
, count(*) as total
from tb_student
group by stu_sex;
group by stu_sex;
-- 查询每个学院学生人数
select col_id as 学院编号,
count(*) as 人数
-- 30. 查询每个学院学生人数(分组和聚合函数)
select col_id
, count(*) as total
from tb_student
group by col_id;
group by col_id
with rollup;
-- 查询每个学院男女学生人数
select col_id as 学院编号,
case stu_sex when 1 then '男' else '女' end as 性别,
count(*) as 人数
-- 31. 查询每个学院男女学生人数(分组和聚合函数)
select col_id
, case stu_sex when 1 then '男' else '女' end as stu_sex
, count(*) as total
from tb_student
group by col_id, stu_sex;
group by col_id, stu_sex;
-- 查询每个学生的学号和平均成绩
select stu_id as 学号,
round(avg(score), 2) as 平均成绩
-- 32. 查询选课学生的学号和平均成绩(分组和聚合函数)
select stu_id
, round(avg(score), 1) as avg_score
from tb_record
group by stu_id;
group by stu_id;
-- 查询平均成绩大于等于90分的学生的学号和平均成绩
-- 方法一:
select stu_id as 学号,
round(avg(score), 2) as 平均成绩
-- 33. 查询平均成绩大于等于90分的学生的学号和平均成绩(分组和聚合函数)
-- 结论分组前的筛选使用where子句分组后的筛选使用having子句
select stu_id
, round(avg(score), 1) as avg_score
from tb_record
group by stu_id
having 平均成绩 >= 90;
group by stu_id
having avg(score) >= 90;
-- 方法二:
select *
from ( select stu_id as 学号,
round(avg(score), 2) as 平均成绩
-- 34. 查询所有课程成绩大于80分的同学的学号(分组和聚合函数)
select stu_id
from tb_record
group by stu_id) as t
where 平均成绩 >= 90;
group by stu_id
having min(score) > 80;
-- 查询1111、2222、3333三门课程平均成绩大于等于90分的学生的学号和平均成绩
select stu_id as 学号,
round(avg(score), 2) as 平均成绩
-- Error Code: 1242. Subquery returns more than 1 row
select stu_id
, stu_name
from tb_student
where stu_id in (select stu_id
from tb_record
where cou_id in (1111, 2222, 3333)
group by stu_id
having avg(score) >= 90;
group by stu_id
having min(score) > 80);
-- 35. 查询年龄最大的学生的姓名(嵌套查询)
-- 嵌套查询/子查询:把一个查询的结果作为另外一个查询的一部分来使用
select @a := min(stu_birth)
from tb_student;
select stu_name
from tb_student
where stu_birth = @a;
-- 嵌套查询:把一个查询的结果作为另外一个查询的一部分来使用
select stu_name
from tb_student
where stu_birth = (select min(stu_birth)
from tb_student);
-- 查询选了两门以上的课程的学生姓名
-- 36. 查询选了两门以上的课程的学生姓名(嵌套查询/分组/数据筛选)
select stu_name
from tb_student
where stu_id in ( select stu_id
where stu_id in (select stu_id
from tb_record
group by stu_id
having count(*) > 2);
-- 查询学生的姓名、生日和所在学院名称
-- 方法一:
select stu_name,
stu_birth,
col_name
-- 37. 查询学生的姓名、生日和所在学院名称(连接查询)
select stu_name
, stu_birth
, col_name
from tb_student, tb_college
where tb_student.col_id = tb_college.col_id;
-- 方法二:
select stu_name,
stu_birth,
col_name
select stu_name
, stu_birth
, col_name
from tb_student inner join tb_college
on tb_student.col_id = tb_college.col_id;
-- 方法三:
select stu_name,
stu_birth,
col_name
select stu_name
, stu_birth
, col_name
from tb_student natural join tb_college;
-- 查询学生姓名、课程名称以及成绩
-- 方法一:
select stu_name,
cou_name,
score
-- 38. 查询学生姓名、课程名称以及成绩(连接查询)
select stu_name
, cou_name
, score
from tb_student, tb_course, tb_record
where tb_student.stu_id = tb_record.stu_id
and tb_course.cou_id = tb_record.cou_id
and score is not null;
-- 方法二:
select stu_name,
cou_name,
score
from tb_student inner join tb_record inner join tb_course
select stu_name
, cou_name
, score
from tb_student
inner join tb_record
on tb_student.stu_id = tb_record.stu_id
and tb_course.cou_id = tb_record.cou_id
inner join tb_course
on tb_course.cou_id = tb_record.cou_id
where score is not null;
-- 方法三:
select stu_name,
cou_name,
score
from tb_student natural join tb_record natural join tb_course
select stu_name
, cou_name
, score
from tb_student
natural join tb_record
natural join tb_course
where score is not null;
-- 补充上面的查询结果取前5条数据
select stu_name,
cou_name,
score
from tb_student natural join tb_record natural join tb_course
-- 39. 上面的查询结果按课程和成绩排序取前5条数据(分页查询)
select stu_name
, cou_name
, score
from tb_student
natural join tb_record
natural join tb_course
where score is not null
order by stu_id asc, score desc
order by cou_id asc, score desc
limit 5;
-- 补充上面的查询结果取第6-10条数据
select stu_name,
cou_name,
score
from tb_student inner join tb_record inner join tb_course
on tb_student.stu_id = tb_record.stu_id
and tb_course.cou_id = tb_record.cou_id
order by stu_id asc, score desc
limit 5
offset 5;
-- 补充上面的查询结果取第11-15条数据
select stu_name,
cou_name,
score
from tb_student natural join tb_record natural join tb_course
-- 40. 上面的查询结果按课程和成绩排序取第6-10条数据(分页查询)
select stu_name
, cou_name
, score
from tb_student
natural join tb_record
natural join tb_course
where score is not null
order by stu_id asc, score desc
order by cou_id asc, score desc
limit 5
offset 10;
offset 5;
-- 查询选课学生的姓名和平均成绩
select stu_name,
avg_score
from tb_student t1 inner join ( select stu_id,
round(avg(score), 2) as avg_score
from tb_record
group by stu_id) t2
on t1.stu_id = t2.stu_id;
-- 41. 上面的查询结果按课程和成绩排序取第11-15条数据(分页查询)
select stu_name
, cou_name
, score
from tb_student
natural join tb_record
natural join tb_course
where score is not null
order by cou_id asc, score desc
limit 5
offset 10;
-- 查询学生的姓名和选课的数量
select stu_name,
total
from tb_student t1 natural join ( select stu_id,
count(*) as total
-- 42. 查询选课学生的姓名和平均成绩(嵌套查询和连接查询)
select stu_name
, avg_score
from tb_student
natural join (select stu_id
, avg(score) as avg_score
from tb_record
group by stu_id) t2;
group by stu_id) as tmp;
-- 查询每个学生的姓名和选课数量(左外连接和子查询)
select stu_name as 姓名,
coalesce (total, 0) as 选课数量
from tb_student t1 left join ( select stu_id,
count(*) as total
-- 43. 查询学生的姓名和选课的数量(嵌套查询和连接查询)
select stu_name
, total
from tb_student
inner join (select stu_id
, count(*) as total
from tb_record
group by stu_id) t2
on t1.stu_id = t2.stu_id;
group by stu_id) as tmp
on tb_student.stu_id = tmp.stu_id;
-- 44. 查询所有学生的姓名和选课数量(左外连接和嵌套查询)
-- 左外连接把左表写在join左边的表所有的数据都拿到不满足连表条件的地方填充null - left outer join
-- 右外连接把右表写在join右边的表所有的数据都拿到不满足连表条件的地方填充null - right outer join
-- 全外连接把左表和右表的数据全部拿到即便它们不满足连表条件MySQL不支持全外连接 - full outer join
select stu_name
, coalesce(total, 0) as total
from tb_student
left join (select stu_id
, count(*) as total
from tb_record
group by stu_id) as tmp
on tb_student.stu_id = tmp.stu_id;
-- 45. 查询没有选课的学生的姓名(左外连接和数据筛选)
select stu_name
from tb_student
left join tb_record
on tb_student.stu_id = tb_record.stu_id
where tb_record.stu_id is null;
```
上面的 DQL 有几个地方需要加以说明:

2
第44课.SQL详解之DCL.md 100644 → 100755
View File

@ -1,4 +1,4 @@
## SQL详解之DCL
## 第44课SQL详解之DCL
数据库服务器通常包含了非常重要的数据,可以通过访问控制来确保这些数据的安全,而 DCL 就是解决这一问题的它可以为指定的用户授予访问权限或者从指定用户处召回指定的权限。DCL 对数据库管理员来说非常重要,因为用户权限的管理关系到数据库的安全。简单的说,我们可以通过 DCL 允许受信任的用户访问数据库,阻止不受信任的用户访问数据库,同时还可以通过 DCL 将每个访问者的的权限最小化(让访问者的权限刚刚够用)。

2
第45课.索引.md 100644 → 100755
View File

@ -1,4 +1,4 @@
## 索引
## 第45课索引
索引是关系型数据库中用来提升查询性能最为重要的手段。关系型数据库中的索引就像一本书的目录,我们可以想象一下,如果要从一本书中找出某个知识点,但是这本书没有目录,这将是意见多么可怕的事情!我们估计得一篇一篇的翻下去,才能确定这个知识点到底在什么位置。创建索引虽然会带来存储空间上的开销,就像一本书的目录会占用一部分篇幅一样,但是在牺牲空间后换来的查询时间的减少也是非常显著的。

2
第46课.视图+函数+过程.md 100644 → 100755
View File

@ -1,4 +1,4 @@
## 视图、函数和过程
## 第46课视图、函数和过程
为了讲解视图、函数和过程,我们首先用下面的 DDL 和 DML 创建名为 hrs 的数据库并为其二维表添加如下所示的数据。

2
第47课.MySQL新特性.md 100644 → 100755
View File

@ -1,4 +1,4 @@
## MySQL 新特性
## 第47课MySQL 新特性
#### JSON类型

View File

@ -1,4 +1,4 @@
## Python程序接入MySQL数据库
## 第48课Python程序接入MySQL数据库
在 Python3 中,我们可以使用`mysqlclient`或者`pymysql`三方库来接入 MySQL 数据库并实现数据持久化操作。二者的用法完全相同,只是导入的模块名不一样。我们推荐大家使用纯 Python 的三方库`pymysql`,因为它更容易安装成功。下面我们仍然以之前创建的名为`hrs`的数据库为例,为大家演示如何通过 Python 程序操作 MySQL 数据库实现数据持久化操作。