2024.4.2 Tuesday
接上文【WEEK6】 【DAY1】DQL查询数据-第一部分【中文版】
目录
- 4.4.连接查询
- 4.4.1.JOIN 对比
- 4.4.2.七种JOIN
- 4.4.3.例
- 4.4.3.1.本例中INNER JOIN和RIGHT JOIN结果相同
- 4.4.3.2.LEFT JOIN
- 4.4.3.3.查询缺考的同学
- 4.4.3.4.思考题:查询参加了考试的同学信息(学号、学生姓名、科目名称、分数)
- 4.4.3.5.自连接(了解)
- 表自己和自己连接,核心是一张表拆成两张一样的表
- 查询学员所属的年级(学号、姓名、年级名称)
- 查询科目所属的年级(科目名称,年级名称)
- 查询参加了'高等数学-1'考试的同学信息(学号、学生姓名、科目名称、分数)
- 4.5.排序和分页
- 4.5.1.排序
- 4.5.1.1.ORDER BY 通过哪个字段排序、怎么排
- 4.5.2.分页
- 4.5.2.1.显示降序排列的跳过了最高成绩的五条数据
- 4.5.2.2.查询 高等数学-3 课程成绩排名前10的学生,而且分数不低于80 的学生信息(学号、姓名、课程名称、分数)
- 4.6.子查询
- 4.6.1.查询 高等数学-3 所有考试结果(学号、课程编号、成绩)降序排列
- 4.6.2.1.方式1:使用连接查询+子查询
- 4.6.1.2.方式2:使用子查询(方式:由里及外)
- 4.6.2.查询课程‘高等数学-4’分数大于80的同学的学号、姓名
- 4.6.2.1.方式1:使用连接查询+子查询
- 4.6.2.2.方式2:使用连接查询
- 4.6.2.3.方式3:使用子查询
- 4.6.3.练习题
- 4.6.3.1.查 C语言-1 的前5名学生的成绩信息(学号,姓名,分数)
- 4.6.3.2.使用子查询,查询刘福同学所在的年级名称
- 4.7.分组和过滤
4.4.连接查询
4.4.1.JOIN 对比
操作符名称 | 描述 |
---|---|
INNER JOIN | 如果表中至少一个匹配,则返回行 |
LEFT JOIN | 即使右表中没有匹配,也从左表中返回所有的行 |
RIGHT JOIN | 即使左表中没有匹配,也从右表中返回所有的行 |
4.4.2.七种JOIN
4.4.3.例
/*
连接查询
如需要多张数据表的数据进行查询,则可通过连接运算符实现多个查询
内连接 inner join
查询两个表中的结果集中的交集
外连接 outer join
左外连接 left join
(以左表作为基准,右边表来一一匹配,匹配不上的,返回左表的记录,右表以NULL填充)
右外连接 right join
(以右表作为基准,左边表来一一匹配,匹配不上的,返回右表的记录,左表以NULL填充)
等值连接和非等值连接
自连接
*/
-- 联表查询join --
-- 查询参加了考试的同学的学号、姓名、分数,科目编号
/*思路
1. 分析思路,分析每个需要查询的字段分别来自哪些表,
2. 确定使用哪种连接查询(单独查询某个表后的结果要能连成完整的需求的表):7种
-> 确定交叉点(这两个表中哪个数据是相同的)
判断的条件:根据两张表中相同的字段名联立,如:student表中的studentNo = result表中的studentNo
*/
-- JOIN +连接的表 + ON +判断的条件 连接查询(一个具体的语法)
-- WHERE 等值查询
4.4.3.1.本例中INNER JOIN和RIGHT JOIN结果相同
-- INNER JOIN
SELECT s.studentNo, studentName, SubjectNo, StudentResult -- 交叉点的字段名要声明使用哪一张表里的
FROM student AS s
INNER JOIN result AS r
WHERE s.studentNo = r.studentNo -- on是连表前的条件,where是连表后的过滤
-- RIGHT JOIN,以右表的字段为准
SELECT s.studentNo, studentName, SubjectNo, StudentResult
FROM student AS s -- 左表
RIGHT JOIN result AS r -- 右表
ON s.studentNo = r.studentNo
4.4.3.2.LEFT JOIN
-- LEFT JOIN,以左表的字段为准
-- 和右连接的区别:显示了没有考试成绩的人员的相关信息
SELECT s.studentNo, studentName, SubjectNo, StudentResult
FROM student AS s -- 右表
LEFT JOIN result AS r -- 左表
ON s.studentNo = r.studentNo
4.4.3.3.查询缺考的同学
-- 查询缺考的同学
SELECT s.studentNo, studentName, SubjectNo, StudentResult
FROM student s -- 右表
LEFT JOIN result r -- 左表
ON s.studentNo = r.studentNo
WHERE StudentResult IS NULL
4.4.3.4.思考题:查询参加了考试的同学信息(学号、学生姓名、科目名称、分数)
-- 思考题:查询参加了考试的同学信息(学号、学生姓名、科目名称、分数)
/*思路
1. 分析思路,分析每个需要查询的字段分别来自哪些表,student、result、subject连接查询
2. 确定使用哪种连接查询(单独查询某个表后的结果要能连成完整的需求的表):7种
-> 确定交叉点(这两个表中哪个数据是相同的)
判断的条件:student表中的studentNo = result表中的studentNo
*/
-- 10~11两行(第一个连接处)from这里是左表 join这里是右表 选择以哪张表作为基准 决定用left还是right
SELECT s.studentNo, studentName, subjectName, `StudentResult`
FROM student s
RIGHT JOIN result r
ON r.studentNo = s.studentNo
INNER JOIN `subject` sub
ON r.subjectNo = sub.subjectNo
#标准思考步骤
-- 我要查询哪些数据 -> SELECT ...
-- 从哪几个表中查 -> FROM 某表 JOIN 要连接的某表 ON 这俩表的交叉条件
-- 假设存在多张表查询,则反复上一步,先从连接两张表开始
4.4.3.5.自连接(了解)
表自己和自己连接,核心是一张表拆成两张一样的表
-
父类
-
子类
-
最终希望的查询结果
#自连接
-- 编写SQL语句,将栏目的父子关系呈现出来 (父栏目名称,子栏目名称)
-- 查询父子信息:把一张表拆成两张一模一样的表
SELECT a.`categoryName` AS '父栏目', b.`categoryName` AS '子栏目'
FROM `category` AS a, `category` AS b
WHERE a.`categoryid` = b.`pid`
查询学员所属的年级(学号、姓名、年级名称)
-- 查询学员所属的年级(学号、姓名、年级名称)
SELECT studentNo, studentName, `GradeName`
FROM student s
INNER JOIN `grade` g
ON s.`GradeID` = g.`GradeID`
查询科目所属的年级(科目名称,年级名称)
-- 查询科目所属的年级(科目名称,年级名称)
SELECT `SubjectName`,`GradeName`
FROM `subject` sub
INNER JOIN `grade` g
ON sub.`GradeID` = g.`GradeID`
查询参加了’高等数学-1’考试的同学信息(学号、学生姓名、科目名称、分数)
-- 查询参加了'高等数学-1'考试的同学信息(学号、学生姓名、科目名称、分数)
SELECT s.`StudentNo`, `StudentName`, `SubjectName`, `StudentResult`
FROM student s
INNER JOIN `result` r
ON s.StudentNo = r.StudentNo
INNER JOIN `subject` sub
ON r.`SubjectNo` = sub.`SubjectNo`
WHERE subjectName = '高等数学-1'
4.5.排序和分页
4.5.1.排序
4.5.1.1.ORDER BY 通过哪个字段排序、怎么排
语法 : ORDER BY
ORDER BY 语句用于根据指定的列对结果集进行排序。
ORDER BY 语句默认按照ASC升序对记录进行排序。
如果您希望按照降序对记录进行排序,可以使用 DESC 关键字。
-- 分页limit 和排序order by --
#排序:升序是ASC,降序是DESC
#语法:ORDER BY 通过哪个字段排序、怎么排
SELECT s.`StudentNo`, `StudentName`, `SubjectName`, `StudentResult`
FROM student s
INNER JOIN `result` r
ON s.StudentNo = r.StudentNo
INNER JOIN `subject` sub
ON r.`SubjectNo` = sub.`SubjectNo`
WHERE subjectName = '高等数学-1'
ORDER BY StudentResult DESC -- 查询的结果根据成绩‘降序’排序
-- 只需把DESC修改成ASC即可将查询的结果根据成绩‘升序’排序
4.5.2.分页
语法 : SELECT * FROM table LIMIT [offset偏移量(跳过offset的页数),] rows(每一页有多少数据) | rows OFFSET offset
好处 : (用户体验,网络传输,查询压力)
4.5.2.1.显示降序排列的跳过了最高成绩的五条数据
#分页
/*
第一页:LIMIT 0,5(跳过0条数据,这页5条数据)
第二页:LIMIT 5,5(跳过5条数据,这页5条数据)
第三页:LIMIT 10,5(跳过10条数据,这页5条数据)
......
第N页:LIMIT (pageNo - 1)*pageSize, pageSize
其中,pageNo指页码,pageSize指单个页面显示的条数,总页数=|_总条数/每页条数_|
*/
-- 显示降序排列的跳过了最高成绩的五条数据
SELECT s.`StudentNo`, `StudentName`, `SubjectName`, `StudentResult`
FROM student s
INNER JOIN `result` r
ON s.StudentNo = r.StudentNo
INNER JOIN `subject` sub
ON r.`SubjectNo` = sub.`SubjectNo`
WHERE subjectName = '高等数学-1'
ORDER BY StudentResult DESC, StudentNo
LIMIT 1,5
4.5.2.2.查询 高等数学-3 课程成绩排名前10的学生,而且分数不低于80 的学生信息(学号、姓名、课程名称、分数)
-- 查询 高等数学-3 课程成绩排名前10的学生,而且分数不低于80 的学生信息(学号、姓名、课程名称、分数)
SELECT s.`StudentNo`, `StudentName`, `SubjectName`, `StudentResult`
FROM `student` s
INNER JOIN `result` r
ON s.StudentNo = r.StudentNo
INNER JOIN `subject` sub
ON r.`SubjectNo` = sub.`SubjectNo`
WHERE subjectName = '高等数学-3' AND StudentResult >= 80
ORDER BY StudentResult DESC, StudentNo
LIMIT 0,10
4.6.子查询
4.6.1.查询 高等数学-3 所有考试结果(学号、课程编号、成绩)降序排列
4.6.2.1.方式1:使用连接查询+子查询
-- 子查询 --
-- 1.查询 高等数学-3 所有考试结果(学号、课程编号、成绩)降序排列
#方式1:使用连接查询
SELECT `StudentNo`, sub.`SubjectNo`, `StudentResult` -- 或者r.SubjectNo亦可
FROM `result` r
INNER JOIN `subject` sub
ON r.SubjectNo = sub.SubjectNo
WHERE SubjectName = '高等数学-3'
ORDER BY StudentResult DESC
4.6.1.2.方式2:使用子查询(方式:由里及外)
#方式二:使用子查询(方式:由里及外)
SELECT `StudentNo`, `SubjectNo`, `StudentResult`
FROM `result`
WHERE SubjectNo = (
SELECT SubjectNo
FROM `subject`
WHERE SubjectName = '高等数学-3'
)
ORDER BY StudentResult DESC
4.6.2.查询课程‘高等数学-4’分数大于80的同学的学号、姓名
4.6.2.1.方式1:使用连接查询+子查询
-- 2.查询课程‘高等数学-4’分数大于80的同学的学号、姓名
#方式1:使用连接查询+子查询
-- 第一部分:有获得(任意一科)分数大于80分的学生学号、姓名
SELECT DISTINCT s.`StudentNo`, `StudentName` -- 不加DISTINCT则每个符合条件的查询结果都会出现(同一个人名和学号可能出现多次)
FROM student s
INNER JOIN result r
ON r.StudentNo = s.StudentNo -- 到这里是(任意一门)有成绩的学生
WHERE `StudentResult` > 80
-- 第二部分:在此基础上再增加科目‘高等数学-4’,不想再连表查询->改为查询该课的编号
SELECT DISTINCT s.`StudentNo`, `StudentName`
FROM student s
INNER JOIN result r
ON r.StudentNo = s.StudentNo
WHERE `StudentResult` > 80 AND `SubjectNo` = (
SELECT SubjectNo
FROM `subject`
WHERE `SubjectName` = '高等数学-4'
)
4.6.2.2.方式2:使用连接查询
#方式2:使用连接查询
SELECT DISTINCT s.`StudentNo`, `StudentName`
FROM student s
INNER JOIN result r
ON r.StudentNo = s.StudentNo
INNER JOIN `subject` sub
ON r.SubjectNo = sub.SubjectNo
WHERE `StudentResult` > 80 AND SubjectName = '高等数学-4'
4.6.2.3.方式3:使用子查询
#方式3:使用子查询
SELECT StudentNo, StudentName FROM student WHERE StudentNo IN ( -- IN最好用等号替换,因为只有一个条件时=的查询效率更高
SELECT StudentNo FROM result WHERE StudentResult > 80 AND SubjectNo = (
SELECT SubjectNo FROM `subject` WHERE `SubjectName` = '高等数学-4'
)
)
4.6.3.练习题
4.6.3.1.查 C语言-1 的前5名学生的成绩信息(学号,姓名,分数)
/*
练习题目:
查 C语言-1 的前5名学生的成绩信息(学号,姓名,分数)
使用子查询,查询刘福同学所在的年级名称
*/
-- 1
SELECT s.StudentNo, StudentName, StudentResult
FROM student s
INNER JOIN result r
ON s.StudentNo = r.StudentNo
WHERE SubjectNo = (
SELECT SubjectNo FROM `subject` WHERE SubjectName = 'C语言-1'
)
ORDER BY StudentResult DESC
LIMIT 0,5
4.6.3.2.使用子查询,查询刘福同学所在的年级名称
-- 2
SELECT GradeName FROM grade WHERE GradeID = (
SELECT GradeID FROM student WHERE StudentName = '刘福'
)
4.7.分组和过滤
详情见:5.2.5.题目
【WEEK6】 【DAY3】MySQL函数【中文版】