【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只能在同一张表中使用

相关推荐
计算机学姐1 小时前
基于微信小程序的民宿预订管理系统
java·vue.js·spring boot·后端·mysql·微信小程序·小程序
云和恩墨2 小时前
云计算、AI与国产化浪潮下DBA职业之路风云变幻,如何谋破局启新途?
数据库·人工智能·云计算·dba
明月看潮生2 小时前
青少年编程与数学 02-007 PostgreSQL数据库应用 11课题、视图的操作
数据库·青少年编程·postgresql·编程与数学
阿猿收手吧!2 小时前
【Redis】Redis入门以及什么是分布式系统{Redis引入+分布式系统介绍}
数据库·redis·缓存
奈葵2 小时前
Spring Boot/MVC
java·数据库·spring boot
leegong231112 小时前
Oracle、PostgreSQL该学哪一个?
数据库·postgresql·oracle
中东大鹅3 小时前
MongoDB基本操作
数据库·分布式·mongodb·hbase
夜光小兔纸3 小时前
Oracle 普通用户连接hang住处理方法
运维·数据库·oracle
兩尛4 小时前
订单状态定时处理、来单提醒和客户催单(day10)
java·前端·数据库
web2u5 小时前
MySQL 中如何进行 SQL 调优?
java·数据库·后端·sql·mysql·缓存