MYSQL--- 聚合查询,分组查询和联合查询

(一).聚合查询

1.概念

聚合查询本质上是针对数据表中的行和行进行运算

2.部分函数

|----------------------|----------------------------|
| 函数 | 说明 |
| COUNT(DISTINCT expr) | 返回查询到的数据的数量(统计记录的行数) |
| SUM(DISTINCT expr) | 返回查询到的数据的总和,不是数字则没有意义 |
| AVG(DISTINCT expr) | 返回查询到的数据的平均值,不是数字则没有意义 |
| MAX(DISTINCT expr) | 返回查询到的数据的最大值,不是数字则没有意义 |
| MIN(DISTINCT expr) | 返回查询到的数据的最小值,不是数字则没有意义 |

3.演示

这是我创建的一个exam表

(1).COUNT

统计所有的行

count (列名)

(2).SUM(列名)

把查询结果中所有行的指定列进行相加,列的数据类型必须是数值类型,否则算出的结果将毫无意义

在SUM求和时,NULL值不参与运算

如果计算的列为非数字型,则毫无意义,同时会报警告

(3).AVG(列名)

对所有行的指定列进行求平均值运算

求所有同学的语文成绩平均值

求语数英三门课的总分的平均值

(4)MIN(),MAX()

求所有行中指定的列的最大值和最小值

查找语文成绩的最高分和英语成绩的最低分

查找出语文成绩的最高分和最低分

(二).分组查询

1. group by 子句

(1).概念

使用group by子句可以对指定列进行分组查询,再进行分组查询时,SELECT 指定的字段必须是 "分组依据字段(要对哪个列进行分组)",其他字段若想出现在SELECT 中,则必须包含在聚合函数中。

(2).语法

select col1,sum(col2),...... from table group by col1,col2;

col1 表示 "分组的列名"

sum(col2) 表示 "没有被分组的列,但是要显示结果,那么就需要用到联合函数"

table 表示 "表名"

group by 表示"分组查询关键字"

col1,col2 表示"要分组的列名"

(3).示例

这是我创建的一个员工表

i.计算不同角色工资的平均值

2.having

(1).概念

group by子句进行分组后,需要对分组结果再进行条件过滤时,不能使用where语句,需要使用having

注意:where 是对表中每一行的真实数据进行过滤

having是对group by之后,计算出来的结果进行过滤的

(2).示例

i.找出平均薪资大于1万,小于20万的角色

首先先要按照结果进行分组,分组完成后,再对分完组的表进行过滤

注意:where用在from表名的后面,即分组之前,having用在group by 子句的后面,如果需求要对真实数据进行过滤,同时也要对分组的结果进行过滤,那么只需在要合适的位置写where和having 即可

ii.查询每个角色的最高工资,最低工资和平均工资

首先,先要按照角色进行分组,然后使用聚合函数分别求出最高工资,最低工资和平均工资

iii.显示平均工资低于1500的角色和它的平均工资

首先,先要按照角色进行分组,然后计算出平均工资,最后通过平均工资是否低于1500进行过滤

(三).联合查询

1.概念

联合多个表进行查询。在设计数据时把表进行拆分,为了消除表中的字段的依赖关系,例如函数依赖,传递依赖,这时会导致一条SQL查出来的数据,对于业务来说是不完整的,所以就可以使用联合查询,把关系表中的数据全部查出来,在一个数据行显示详细信息。

通过一个例子来看

2.联合查询的执行

(1).首先,联合多张表,取多张表的笛卡尔积

语法:select * from 表名,表名;
取笛卡尔积的过程:

①.先从第一张表中取一条记录,然后再与第二张表中的第一条记录进行组合,生成一条新的记录

②.先从第一张表中取一条记录,然后再与第二张表中的第二条记录进行组合,生成一条新的记录

··············

最后得到一个全排列的结果集

拿刚才的表进行举例

但是这里面有很多无效的数据

可以发现,这些有用的数据都有一个特点,就是 "student2"表中的 "class_id"字段的值和 "class"表中的 "id" 字段的值一样

所以就可以通过连接条件过滤掉无效的数据

(2).通过连接条件过滤掉无效的数据

"student2"表和 "class2"表之间是有主外键关系的,只需要判断两个表中的主外键字段是否相等即可

这样,我们就可以通过连接条件过滤出有效的数据了

(3).通过指定列查询,来精简结果集

注意:查询列表中可以通过表名.列名的方式指定要查询的字段

总结:联合查询(表连接查询)的步骤

①.首先确定要参与查询的表

②.根据表与表之间的主外键关系,确定过滤条件

③.精简查询字段,得到想要的结果

3.内连接

(1).语法

select 字段 from 表1 别名1 [inner] join 表2 别名2 on 连接条件 and 其他条件

inner 可以省略

join 两边时参与查询的表

on 后面跟的是连接条件

select 字段 from 表1 别名1 ,表2 别名2 where 连接条件 and 其他条件

(2).示例

这里我新创建一个表

Ⅰ.查询 " 许仙"同学的成绩

①.首先,先分析涉及到的表

查 "许仙"的成绩,首先会涉及到学生表,其次就是成绩表

②.取 "学生表" 和 "成绩表"的笛卡尔积

这里面有很多数据是无用的,例如图片中用方框框起来的数据,两个student_id 都不一样,所以这样的数据是无效的

③.根据表与表之间的主外键关系,确定过滤条件

首先,成绩表中的student_id 与 学生表中的student_id 是通过主外键建立起的关联字段,所以student_id 必须要一样

④.确认结果集中的过滤条件

题目是 "查找 '许仙'同学的成绩",所以过滤条件是学生名字为 "许仙"

⑤.精简查询列表中的字段

Ⅱ.查询所有同学的总成绩,及同学的个人信息

①.首先,先分析涉及到的表

查询所有同学的总成绩及个人信息,首先会涉及到的就是 "成绩表",由于还涉及到"个人信息",所以还会涉及到 "学生表"

②.取 "学生表" 和 "成绩表"的笛卡尔积

这里面有很多数据是无用的,例如图片中用方框框起来的数据,两个student_id 都不一样,所以这样的数据是无效的

③.根据表与表之间的主外键关系,确定过滤条件

首先,成绩表中的student_id 与 学生表中的student_id 是通过主外键建立起的关联字段,所以student_id 必须要一样

④.确认结果集中的过滤条件

题目是"查询所有同学的总成绩",所以我们需要对这些同学进行按照student_id进行分组,然后计算每位学生的成绩总分

⑤.在查询列表中确定要查询的列

Ⅲ.查询所有同学每门课的成绩及同学的个人信息

①.先分析涉及到的表

首先,根据题目分析,涉及到的第一个表就是成绩表,因为查询的是"每门课"的成绩,所以还会涉及到课程表,还要显示个人信息,所以会涉及到一个学生表

所以会涉及到 "学生表","班级表" 和 "成绩表"

②.取涉及到的表的笛卡尔积

③.根据表与表之间的主外键关系,确定过滤条件

首先,学生表里面的student_id,要和成绩表里面的student_id对应起来,同时课程表里面的course_id,要和成绩表里面的course_id对应起来

④.确定查询的过滤条件where

这个不需要

⑤.精简查询字段

4.外连接

(1).概念

外连接分为左外连接和右外连接。如果联合查询,左侧的表完全显示就说是左外连接,右侧的表完全显示就是右外连接。

(2).示例

1.测试外连接

右外连接

左外连接

这是现在的student2表

2.查询哪位同学没有考试成绩

思路:要查询没有考试成绩的同学,那么这个同学就在学生表中有记录,但是在成绩表中没有记录

直接使用左查询进行查找

先使用左查询,查出所有同学的成绩

然后再去找成绩表里面成绩为空的同学

5.自连接

(1).概念

自连接,自己与自己进行连接,可以把行转换成列,在查询的时候可以使用where条件进行过滤也就是说可以实现行与行之间的比较功能

(2).示例

Ⅰ.显示所有"计算机原理"成绩比"java"成绩高的成绩信息

①.确认涉及到的表

首先,肯定会涉及到"成绩表","学生表",还有一个就是 "课程表",因为我们需要确认"计算机原理"和 "java"的课程编号,所以需要涉及到 "课程表",同时,要明白,我们要涉及到两个成绩表和两个课程表,因为一个成绩表是看 "计算机组成原理"的成绩的,另一个成绩表是看 "java"的成绩的。一个课程表是看"计算机组成原理"的,一个课程表是看"java"的

②.取涉及到的表的笛卡尔积

③.根据表与表之间的主外键关系,确定过滤条件

首先,学生表里面的student_id,要和成绩表(s1,s2)里面的student_id对应起来,同时课程表c1里面的course_id,要和成绩表s1里面的course_id对应起来,课程表c2里面的course_id,要和成绩表s2里面的course_id 对应起来

④.确定查询的过滤条件where

我们要查的是课程名为"计算机原理"和 "java",所以where的过滤条件就出来了,同时 "计算机原理"的成绩要高于 "java"

⑤.精简查询字段

6.子查询

(1).概念

子查询,也叫嵌套查询。子查询是把一条SQL的查询结果,当作另一条SQL的查询条件,同时,可以嵌套很多层。

(2).语法

select 列名 from 表名 where 表名.列名 =(select 列名 from 表名 where 表名.列名)

括号中的select语句为子查询

子查询是由很多条SQL语句组成的,也可以把子查询拆分成一条一条单独的语句去执行,最后把结果和条件拼装在一起,得到查询的结果。

(3).单行子查询

返回一行记录的子查询

示例:

查询与 "不想毕业" 同学的同班同学

①.确认涉及到的表

由于学生表中包含了班级的id,所以只涉及到了一个学生表

②.先查出 "不想毕业"同学的班级编号

③.以 "不想毕业"同学的班级编号为条件,查出"不想毕业"同学的同班同学

④.使用单行子查询来完成

(4).多行子查询

返回多行记录的子查询,返回的是一个集合,集合中包含多个对象

语法:

select 列名 from 表名 where 表名.列名 in(select 列名 from 表名 where ······)

[NOT] IN
示例:

查询 "语文" 或 "英语" 课程的成绩信息

①.涉及到的表

首先,我们要先通过 "课程表" 来找到 "语文" 和 "英文" 的课程编号,所以会涉及到 "课程表",然后再在成绩表中找到 "语文"和 "英文"的课程编号所以对应的成绩,所以会涉及到 "成绩表"

②.在课程表中找到 "语文"和 "英文"的成绩编号

③.再根据课程编号,在成绩表中找到对应的成绩

④.使用多行子查询来完成

[NOT] EXISTS

语法:select * from 表名 where exists (select * from 表名1)

exists 后面括号中的查询语句,如果有结果返回,则执行外层的查询,如果返回的是一个空结果集,则不执行外层的查询

示例:

(5).多列子查询的多列包含

外层查询中的条件字段,与内层查询中的结果,一 一作比较,如果相等则满足条件,如果有一个不相等,则不满足条件

示例:

查询重复的分数

在score表中,我已经插入了很多重复的数据,下面就要找出这些重复的数据

思路:可以通过分组查询,如何判断数据是否重复?只有当,课程的id,学生的id,和score分数都相等的时候,才能判定其为重复的分数,如何使用count(*)来统计条数,如果条数>1,说明就有重复的分数

然后将分组完的数据进行过滤,过滤出count(*) >1的成绩

使用外层查询完成

7.在from子句中使用子查询

(1).概念:

子查询语句出现在from子句中,可以把一个查询的结果当作一个临时表用

(2).示例

查询所有比 "中文系2019级3班"平均分高的成绩信息

思路:先在班级表中找到 "中文系2019级3班"对应的班级编号,然后通过班级编号找到在学生表中与班级编号相同的学生,然后在成绩表中找出这些学生的成绩,然后取平均分,然后再在成绩表中找出比平均分高的成绩信息。

①.算出 "中文系2019级3班" 的平均分

通过上面的思路,可以看出,涉及到的表有 "学生表","班级表","成绩表"

然后依据思路,算出平均分

②.再用成绩表学生的真实成绩与这个临时表中的平均分作比较,然后找出高于平均分的成绩信息

(四).合并查询

1.概念

合并多个查询结果到一个结果集当中

关键字:union union all

适用场景:多表中查询,在单表查询的时候,建议使用or来查询,在多表中时,无法使用

or,此时就可以使用 union 和union all

示例:

这是我在表student3中插入的数据

下面就是通过union连接

列不匹配的情况

2.union 和 union all 的区别

union 会自动去掉结果集中的重复行

union all 不会去掉结果集中的重复行

我在student表中插入了几条数据,这几条数据是和student3中重复的

下面就来看下union 和union all 的区别

(五).扩展

根据一张表结构创建一个新表

语法:create table 表名1 like 表名2

相关推荐
一 乐3 小时前
校园二手交易|基于springboot + vue校园二手交易系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端
啦啦啦_99993 小时前
Redis-0-业务逻辑
数据库·redis·缓存
自不量力的A同学4 小时前
Redisson 4.2.0 发布,官方推荐的 Redis 客户端
数据库·redis·缓存
Exquisite.4 小时前
Mysql
数据库·mysql
全栈前端老曹4 小时前
【MongoDB】深入研究副本集与高可用性——Replica Set 架构、故障转移、读写分离
前端·javascript·数据库·mongodb·架构·nosql·副本集
R1nG8634 小时前
CANN资源泄漏检测工具源码深度解读 实战设备内存泄漏排查
数据库·算法·cann
阿钱真强道5 小时前
12 JetLinks MQTT直连设备事件上报实战(继电器场景)
linux·服务器·网络·数据库·网络协议
逍遥德5 小时前
Sring事务详解之02.如何使用编程式事务?
java·服务器·数据库·后端·sql·spring
笨蛋不要掉眼泪5 小时前
Redis哨兵机制全解析:原理、配置与实战故障转移演示
java·数据库·redis·缓存·bootstrap