【MySQL篇】聚合查询,联合查询

聚合查询

1 聚合函数

主要对于行与行之间的操作 聚合函数的作用是对一组数据进行计算,通常返回一个单一的结果。它们常用于数据汇总、统计和分析。

常见的统计总数、计算平局值等操作,可以使用聚合函数来实现,常见的聚合函数有:

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

案例:

COUNT

  • 作用:返回某列的非 NULL 值的数量,或返回满足条件的行数。
  • 语法
sql 复制代码
COUNT(column_name)   -- 统计指定列非 NULL 的值的数量
COUNT(*)             -- 统计所有行的数量

当具体对某个列查询的时候 count会关注null值 并且不会包含它
如果对整个表进行count 则不会关注null

SUM()

  • 作用:返回某列数值型数据的总和。
  • 语法
sql 复制代码
SUM(column_name)

求语文分数的总和

求语文+数学+英语分数的总和

AVG()

  • 作用:返回某列数值型数据的平均值。
  • 语法
sql 复制代码
AVG(column_name)

统计总分平均总分

MAX()

  • 作用:返回某列中的最大值。
  • 语法
sql 复制代码
MAX(column_name)

MIN()

  • 作用:返回某列中的最小值。
  • 语法
sql 复制代码
MIN(column_name)

求语文的最高分 和 英语的最低分


GROUP BY子句

SELECT 中使用 GROUP BY 子句可以对指定列进行分组查询。需要满足:使用 GROUP BY 进行分组查询时,SELECT 指定的字段必须是"分组依据字段",其他字段若想出现在SELECT 中则必须包含在聚合函数中。

  • 查询每个岗位的人数

按照role进行分组 ,再根据分组的结果使用count聚合函数统计它的人数即可

  • 统计每个岗位的平均工资
  • 查询每个角色的人数和最高工资、最低工资和平均工资

HAVING

HAVING 是一个用于对查询结果进行过滤的 SQL 语句,它通常与 GROUP BY 一起使用,用于过滤分组后的结果。与 WHERE 不同,HAVING 是在对数据进行分组(GROUP BY)之后进行过滤的,而 WHERE 是在分组之前对数据进行过滤的。

显示平均工资大于10000的角色和它的平均工资


联合查询

实际开发中往往数据来自不同的表,所以需要多表联合查询。多表查询是对多张表的数据取笛卡尔积

啥是笛卡尔积?

  • 笛卡尔积(CROSS JOIN):将两个表中的每一行与另一表的每一行进行组合,生成结果集的行数是两个表行数的乘积,通常会产生非常大的结果集。

示例:

以上所有数据就是笛卡尔积 但是有很多错误信息 他们并不匹配 所有需要进一步细分

此时就可以发现数据一一对应上了 这就是多表查询;

初始化数据,以便下一步的学习

sql 复制代码
insert into classes(name, `desc`) values
('计算机系2019级1班', '学习了计算机原理、C和Java语言、数据结构和算法'),
('中文系2019级3班','学习了中国传统文学'),
('自动化2019级5班','学习了机械自动化');
insert into student(sn, name, qq_mail, classes_id) values
('09982','黑旋风李逵','xuanfeng@qq.com',1),
('00835','菩提老祖',null,1),
('00391','白素贞',null,1),
('00031','许仙','xuxian@qq.com',1),
('00054','不想毕业',null,1),
('51234','好好说话','say@qq.com',2),
('83223','tellme',null,2),
('09527','老外学中文','foreigner@qq.com',2);
insert into course(name) values
('Java'),('中国传统文化'),('计算机原理'),('语文'),('高阶数学'),('英文');
insert into score(score, student_id, course_id) values
-- 黑旋风李逵
(70.5, 1, 1),(98.5, 1, 3),(33, 1, 5),(98, 1, 6),
-- 菩提老祖
(60, 2, 1),(59.5, 2, 5),
-- 白素贞
(33, 3, 1),(68, 3, 3),(99, 3, 5),
-- 许仙
(67, 4, 1),(23, 4, 3),(56, 4, 5),(72, 4, 6),
-- 不想毕业
(81, 5, 1),(37, 5, 5),
-- 好好说话
(56, 6, 2),(43, 6, 4),(79, 6, 6),
-- tellme
(80, 7, 2),(92, 7, 6);

1 内连接

语法:

sql 复制代码
select 字段 from 表1 别名1 [inner] join 表2 别名2 on 连接条件 and 其他条件;
select 字段 from 表1 别名1,表2 别名2 where 连接条件 and 其他条件;

俩种写法都可以;

案例:

(1)查询"许仙"同学的 成绩

首先看到题目先确定查询的信息来自于哪张表?

很明显来自 student表和score表

接着对俩张表进行笛卡尔积

sql 复制代码
select * from student,score;

这些数据是全部排列组合的结果,并不是我们全部想要的;

缩小范围 加上条件 student.id = score.id

sql 复制代码
select * from student,score where student.id = score.student_id;

最后补下其他条件即可

sql 复制代码
 select student.name,score.score from student,score where student.id = score.student_id and student.name = '许仙';

join on 写法

sql 复制代码
 select student.name,score.score from student join score on  student.id = score.student_id and student.name = '许仙';

注意: 如果在实际开发中 谨慎使用笛卡尔积 如果表中数据很大,容易把mysql弄崩溃

(2)查询所有同学的总成绩,及同学的个人信息:

成绩在score表 个人信息在学生表

总成绩需要使用到聚合函数 可以按照学生名字进行分组

sql 复制代码
select * from student,score where student.id = score.student_id group by student.name;

进行求和 并且留下指定列

sql 复制代码
 select student.name,sum(score) as '总成绩' from student,score where student.id = score.student_id group by student.name;

join on 写法:

sql 复制代码
select student.name,sum(score) as '总成绩' from student join score on student.id = score.student_id group by student.name;


3)查询所有同学的成绩,及同学的个人信息:

列出 同学的名称 课程的名字 以及课程的成绩

提取关键词:成绩在score表 同学在student表 个人信息在course表

sql 复制代码
 select * from student,course,score;

数据相当大 对它进行细节划分

sql 复制代码
select * from student,course,score where student.id = score.student_id and score.course_id = course.id;

对列进行精简即可

sql 复制代码
select student.name as '学生名称' , course.name as '科目名称' , score.score from student,course,score where student.id = score.student_id and score.course_id = course.id;

join on 写法

sql 复制代码
select student.name as '学生名称' , course.name as '科目名称' , score.score from student join course on student.id = course.id join score on score.course_id = course.id;

2 外连接

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

语法:

sql 复制代码
-- 左外连接,表1完全显示
select 字段名 from 表名1 left join 表名2 on 连接条件;
-- 右外连接,表2完全显示
select 字段 from 表名1 right join 表名2 on 连接条件;

内连接:

左外连接:

右外连接:

俩张表存在一一对应的情况 ,所有内连接和外连接找到的结果都是一致的;
当修改其中某个值,让它们不保存一一对应的情况

内连接:

左外连接:

右外连接:

当对应不存在的列 会用null填充


3 自连接

自连接是指在同一张表连接自身进行查询。

案例:

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

行与行比较大小 怎么办?

只能将它们转化成列与列比较大小,自连接将可以完成操作 自己与自己笛卡尔积

进行不断筛选

并且让s1 为计算机原理 课程id为3 s2为java 课程id 为1

最后进行大于 筛选

sql 复制代码
select * from score as s1 ,score as s2 where s1.student_id =  s2.student_id and s1.course_id = 3 and s2.course_id = 1 and s1.score > s2.score;

4 子查询

子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询

简单来说就是把多个sql语句写成一个sql;

单行子查询:返回一行记录的子查询

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

思路:在student表中找到"不想毕业" 同学的classes_id 再在student表中找到与它id相同的同学

1.

sql 复制代码
select name from student where classes_id = 1;
sql 复制代码
 select name from student where classes_id = 1 and name != '不想毕业';

一行写完:

sql 复制代码
select name from student where classes_id = (select classes_id from student where name = '不想毕业') and name != '不想毕业';


多行子查询:返回多行记录的子查询

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

思路:在course表中找到"语文"或"英文"课程的id 再在score表找到 id为它们的分数

1.

sql 复制代码
select id from course where name = '语文' or name = '英文';
sql 复制代码
select score from score where course_id in(4,6);

一行写完:

sql 复制代码
 select score from score where course_id in(select id from course where name = '语文' or name = '英文');

5 合并查询

在实际应用中,为了合并多个select的执行结果,可以使用集合操作符 union,union all。使用UNION和UNION ALL时,前后查询的结果集中,字段需要一致。
将最终结果合并在一起,整体过程与执行多个sql操作类似;

查询id小于3,或者名字为"英文"的课程:

sql 复制代码
select * from course where id < 3 union select * from course where name = '英文';

也可以直接使用or;

但是union的作用可以在不同的表的使用 并于合并

而or只能在同一张表中使用

相关推荐
苹果醋34 分钟前
2020重新出发,MySql基础,MySql表数据操作
java·运维·spring boot·mysql·nginx
小蜗牛慢慢爬行5 分钟前
如何在 Spring Boot 微服务中设置和管理多个数据库
java·数据库·spring boot·后端·微服务·架构·hibernate
hanbarger9 分钟前
nosql,Redis,minio,elasticsearch
数据库·redis·nosql
微服务 spring cloud31 分钟前
配置PostgreSQL用于集成测试的步骤
数据库·postgresql·集成测试
先睡33 分钟前
MySQL的架构设计和设计模式
数据库·mysql·设计模式
弗罗里达老大爷35 分钟前
Redis
数据库·redis·缓存
仰望大佬0071 小时前
Avalonia实例实战五:Carousel自动轮播图
数据库·microsoft·c#
学不透java不改名1 小时前
sqlalchemy连接dm8 get_columns BIGINT VARCHAR字段不显示
数据库
一只路过的猫咪1 小时前
thinkphp6使用MongoDB多个数据,聚合查询的坑
数据库·mongodb