聊聊MySQL中的聚合函数,实践掌握分页查询!


本篇文章带大家了解一下mysql内置函数中的聚合函数,并了解一下怎么进行分页查询,希望对大家有所帮助。

聊聊MySQL中的聚合函数,实践掌握分页查询!

MySQL聚合函数和分页查询

参考链接:#MySQL数据库(mysql安装/基础/高级/优化)https://www.bilibili.com/video/BV1iq4y1u7vj

我们在之前了解到了 SQL 单行函数。实际上 SQL 函数还有一类,叫做聚合(或聚集、分组)函数,它是对一组数据进行汇总的函数,输入的是一组数据的集合,输出的是单个值。【相关推荐:mysql视频教程】

1. 聚合函数介绍

什么是聚合函数

聚合函数作用于一组数据,并对一组数据返回一个值。

1.png

聚合函数类型

  • *G()
  • SUM()
  • MAX()
  • MIN()
  • COUNT()

聚合函数语法

2.png

聚合函数不能嵌套调用

比如不能出现类似“*G(SUM(字段名称))”形式的调用。

1.1 *G和SUM函数

可以对数值型数据使用*G 和 SUM 函数。

SELECT *G(salary), MAX(salary),MIN(salary), SUM(salary)
FROM   employees
WHERE  job_id LIKE '%REP%';

1.2 MIN和MAX函数

可以对任意数据类型的数据使用 MIN 和 MAX 函数。

SELECT MIN(hire_date), MAX(hire_date)
FROM employees;

1.3 COUNT函数

  • COUNT(*)返回表中记录总数,适用于任意数据类型
SELECT COUNT(*)
FROM   employees
WHERE  department_id = 50;
  • COUNT(expr) 返回expr不为空的记录总数。
SELECT COUNT(commission_pct)
FROM   employees
WHERE  department_id = 50; //忽略了Null值

计算表中有多少条记录

  • 方式1:count(*)
  • 方式2:count(1)
  • 方式3:count(某具体字段),但是因为忽略了null值,所以不一定对

问题:用count(*),count(1),count(列名)谁好呢?

其实,对于MyISAM引擎的表是没有区别的。这种引擎内部有一计数器在维护着行数,但是COUNT(*)的效率略高

Innodb引擎的表用count(*),count(1)直接读行数,复杂度是O(n),因为innodb真的要去数一遍。但好于具体的count(列名)

问题:能不能使用count(列名)替换count(*)?

不要使用 count(列名)来替代 count(*)count(*)是 SQL92 定义的标准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。

说明:count(*)会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行。

注意:

  • 以上分组函数都忽略null值

  • 可以和distinct搭配实现去重的运算

  • count函数的单独介绍,一般使用count(*)用作统计行数

  • 和分组函数一同查询的字段要求是group by后的字段

2. GROUP BY

2.1 基本使用

3.png

可以使用GROUP BY子句将表中的数据分成若干组,语法如下:

SELECT column, group_function(column)
FROM table
[WHERE	condition]
[GROUP BY  group_by_expression]
[ORDER BY  column];

明确:WHERE一定放在FROM后面

1、 在SELECT列表中所有未包含在组函数中的列都应该包含在 GROUP BY子句中

SELECT   department_id, *G(salary)
FROM     employees
GROUP BY department_id ;

4.png

2、包含在 GROUP BY 子句中的列不必包含在SELECT 列表中

SELECT   *G(salary)
FROM     employees
GROUP BY department_id ;

2.2 使用多个列分组

5.png

SELECT   department_id AS dept_id, job_id, SUM(salary)
FROM     employees
GROUP BY department_id, job_id ;

6.png

2.3 GROUP BY中使用WITH ROLLUP

使用WITH ROLLUP关键字之后,在所有查询出的分组记录之后增加一条记录,该记录计算查询出的所有记录的总和,即统计记录数量。

SELECT department_id,*G(salary)
FROM employees
WHERE department_id > 80
GROUP BY department_id WITH ROLLUP;

注意: 当使用ROLLUP时,不能同时使用ORDER BY子句进行结果排序,即ROLLUP和ORDER BY是互相排斥的,当然这是只在5.7才存在的

3. H*ING(过滤数据)

3.1 基本使用

7.png

过滤分组:H*ING子句

  • 行已经被分组。

  • 使用了聚合函数。

  • 满足H*ING 子句中条件的分组将被显示。

  • H*ING 不能单独使用,必须要跟 GROUP BY 一起使用。

8.png

SELECT   department_id, MAX(salary)
FROM     employees
GROUP BY department_id
H*ING   MAX(salary)>10000 ;

9.png

非法使用聚合函数 : 不能在 WHERE 子句中使用聚合函数来代替过滤条件。如下:

SELECT   department_id, *G(salary)
FROM     employees
WHERE    *G(salary) > 8000
GROUP BY department_id;

练习:查询部门id为10,20,30,40这4个部门中最高工资比10000高的部门信息

#方式1:推荐,执行效率高于方式2.
SELECT department_id,MAX(salary)
FROM employees
WHERE department_id IN (10,20,30,40)
GROUP BY department_id
H*ING MAX(salary) > 10000;

#方式2:
SELECT department_id,MAX(salary)
FROM employees
GROUP BY department_id
H*ING MAX(salary) > 10000 AND department_id IN (10,20,30,40);

结论:

  • 当过滤条件中有聚合函数时,则此过滤条件必须声明在H*ING中。

  • 当过滤条件中没有聚合函数时,则此过滤条件声明在WHERE中或H*ING中都可以。但是,建议大家声明在WHERE中

3.2 WHERE和H*ING的对比

1. 从适用范围上来讲,H*ING的适用范围更广。 
2. 如果过滤条件中没有聚合函数:这种情况下,WHERE的执行效率要高于H*ING

区别1:WHERE 可以直接使用表中的字段作为筛选条件,但不能使用分组中的计算函数作为筛选条件;H*ING 必须要与 GROUP BY 配合使用,可以把分组计算的函数和分组字段作为筛选条件。

这决定了,在需要对数据进行分组统计的时候,H*ING 可以完成 WHERE 不能完成的任务。这是因为,在查询语法结构中,WHERE 在 GROUP BY 之前,所以无法对分组结果进行筛选。H*ING 在 GROUP BY 之后,可以使用分组字段和分组中的计算函数,对分组的结果集进行筛选,这个功能是 WHERE 无法完成的。另外,WHERE排除的记录不再包括在分组中。

区别2:如果需要通过连接从关联表中获取需要的数据,WHERE 是先筛选后连接,而 H*ING 是先连接后筛选。 这一点,就决定了在关联查询中,WHERE 比 H*ING 更高效。因为 WHERE 可以先筛选,用一个筛选后的较小数据集和关联表进行连接,这样占用的资源比较少,执行效率也比较高。H*ING 则需要先把结果集准备好,也就是用未被筛选的数据集进行关联,然后对这个大的数据集进行筛选,这样占用的资源就比较多,执行效率也较低。

小结如下:


优点 缺点
WHERE(分组前筛选) 先筛选数据再关联,执行效率高 不能使用分组中的计算函数进行筛选
H*ING(分组后筛选) 可以使用分组中的计算函数 在最后的结果集中进行筛选,执行效率较低

开发中的选择:

WHERE 和 H*ING 也不是互相排斥的,我们可以在一个查询里面同时使用 WHERE 和 H*ING。包含分组统计函数的条件用 H*ING,普通条件用 WHERE。这样,我们就既利用了 WHERE 条件的高效快速,又发挥了 H*ING 可以使用包含分组统计函数的查询条件的优点。当数据量特别大的时候,运行效率会有很大的差别。一般来讲,能用分组前筛选的,尽量使用分组前筛选,提高效率

4. 回顾:分页查询 ★

SONIFY.io SONIFY.io

设计和开发音频优先的产品和数据驱动的解决方案

SONIFY.io 83 查看详情 SONIFY.io

应用场景:当要显示的数据,一页显示不全,需要分页提交sql请求

语法:

  select 查询列表
  from 表
  【join type join 表2
  on 连接条件
  where 筛选条件
  group by 分组字段
  h*ing 分组后的筛选
  order by 排序的字段】
  limit 【offset,】size;
  offset 要显示条目的起始索引(起始索引从0开始)
  size 要显示的条目个数

特点:

  • limit语句放在查询语句的最后

  • 公式

    select 查询列表
    from 表
    limit (page-1)*size,size;

假设size=10,即每页显示10条记录,page从1开始,即第一页

  • page=1,则显示条目的起始索引为0,页面显示0-10条
  • page=2,则显示条目的起始索引为10,页面显示11-20条
  • page=3,则显示条目的起始索引为20,页面显示21-30条

案例1:查询前五条员工信息

SELECT * FROM employees LIMIT 0,5;
SELECT * FROM employees LIMIT 5;

案例2:查询第11条——第25条

SELECT * FROM employees LIMIT 10,15;

案例3: 有奖金的员工信息,并且工资较高的前10名显示出来

SELECT *
FROM employees 
WHERE commission_pct IS NOT NULL 
ORDER BY salary DESC
LIMIT 10 ;

5. SELECT的执行过程

5.1 SELECT语句的完整结构

#方式1:sql92语法:
SELECT ...,....,...
FROM ...,...,....
WHERE 多表的连接条件
AND 不包含组函数的过滤条件
GROUP BY ...,...
H*ING 包含组函数的过滤条件
ORDER BY ... ASC/DESC
LIMIT ...,...

#方式2:sql99语法
SELECT ...,....,...
FROM ... JOIN ... 
ON 多表的连接条件
JOIN ...
ON ...
WHERE 不包含组函数的过滤条件
AND/OR 不包含组函数的过滤条件
GROUP BY ...,...
H*ING 包含组函数的过滤条件
ORDER BY ... ASC/DESC
LIMIT ...,...

#其中:
#(1)from:从哪些表中筛选
#(2)on:关联多表查询时,去除笛卡尔积
#(3)where:从表中筛选的条件
#(4)group by:分组依据
#(5)h*ing:在统计结果中再次筛选
#(6)order by:排序
#(7)limit:分页

5.2 SELECT执行顺序

你需要记住 SELECT 查询时的两个顺序:

1. 关键字的顺序是不能颠倒的:

SELECT ... FROM ... WHERE ... GROUP BY ... H*ING ... ORDER BY ... LIMIT...

2.SELECT 语句的执行顺序(在 MySQL 和 Oracle 中,SELECT 执行顺序基本相同):

FROM -> WHERE -> GROUP BY -> H*ING -> SELECT 的字段 -> DISTINCT -> ORDER BY -> LIMIT

10.png

比如你写了一个 SQL 语句,那么它的关键字顺序和执行顺序是下面这样的:

SELECT DISTINCT player_id, player_name, count(*) as num # 顺序 5
FROM player JOIN team ON player.team_id = team.team_id # 顺序 1
WHERE height > 1.80 # 顺序 2
GROUP BY player.team_id # 顺序 3
H*ING num > 2 # 顺序 4
ORDER BY num DESC # 顺序 6
LIMIT 2 # 顺序 7

在 SELECT 语句执行这些步骤的时候,每个步骤都会产生一个虚拟表,然后将这个虚拟表传入下一个步骤中作为输入。需要注意的是,这些步骤隐含在 SQL 的执行过程中,对于我们来说是不可见的。

从这里的执行顺序我们也看出来了,因为where是先筛选的,因此group by语句事先分组,参与分组的数据要少,因此执行效率要高

5.3 SQL 的执行原理

SELECT 是先执行 FROM 这一步的。在这个阶段,如果是多张表联查,还会经历下面的几个步骤:

  • 首先先通过 CROSS JOIN 求笛卡尔积,相当于得到虚拟表 vt(virtual table)1-1;

  • 通过 ON 进行筛选,在虚拟表 vt1-1 的基础上进行筛选,得到虚拟表 vt1-2;

  • 添加外部行。如果我们使用的是左连接、右链接或者全连接,就会涉及到外部行,也就是在虚拟表 vt1-2 的基础上增加外部行,得到虚拟表 vt1-3。

当然如果我们操作的是两张以上的表,还会重复上面的步骤,直到所有表都被处理完为止。这个过程得到是我们的原始数据。

当我们拿到了查询数据表的原始数据,也就是最终的虚拟表 vt1,就可以在此基础上再进行 WHERE 阶段。在这个阶段中,会根据 vt1 表的结果进行筛选过滤,得到虚拟表 vt2

然后进入第三步和第四步,也就是 GROUP 和 H*ING 阶段。在这个阶段中,实际上是在虚拟表 vt2 的基础上进行分组和分组过滤,得到中间的虚拟表 vt3vt4

当我们完成了条件筛选部分之后,就可以筛选表中提取的字段,也就是进入到 SELECT 和 DISTINCT 阶段

首先在 SELECT 阶段会提取想要的字段,然后在 DISTINCT 阶段过滤掉重复的行,分别得到中间的虚拟表 vt5-1vt5-2

当我们提取了想要的字段数据之后,就可以按照指定的字段进行排序,也就是 ORDER BY 阶段,得到虚拟表 vt6

最后在 vt6 的基础上,取出指定行的记录,也就是 LIMIT 阶段,得到最终的结果,对应的是虚拟表 vt7

当然我们在写 SELECT 语句的时候,不一定存在所有的关键字,相应的阶段就会省略。

同时因为 SQL 是一门类似英语的结构化查询语言,所以我们在写 SELECT 语句的时候,还要注意相应的关键字顺序,**所谓底层运行的原理,就是我们刚才讲到的执行顺序。**更细致的内容参考后续的高级篇架构

6. 课后练习

综合练习1

1.where子句可否使用组函数进行过滤? No

2.查询公司员工工资的最大值,最小值,平均值,总和

SELECT MAX(salary), MIN(salary), *G(salary), SUM(salary)
FROM employees;

3.查询各job_id的员工工资的最大值,最小值,平均值,总和

SELECT job_id, MAX(salary), MIN(salary), *G(salary), SUM(salary)
FROM employees
GROUP BY job_id;

4.选择具有各个job_id的员工人数

SELECT job_id, COUNT(*)
FROM employees
GROUP BY job_id;

5.查询员工最高工资和最低工资的差距(DIFFERENCE)

SELECT MAX(salary), MIN(salary), MAX(salary) - MIN(salary) DIFFERENCE
FROM employees;

6.查询各个管理者手下员工的最低工资,其中最低工资不能低于6000,没有管理者的员工不计算在内

SELECT manager_id, MIN(salary)
FROM employees
WHERE manager_id IS NOT NULL
GROUP BY manager_id
H*ING MIN(salary) > 6000;

7.查询所有部门的名字,location_id,员工数量和平均工资,并按平均工资降序

SELECT department_name, location_id, COUNT(employee_id), *G(salary) *g_sal
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`
GROUP BY department_name, location_id
ORDER BY *g_sal DESC;

11.png

8.查询每个工种、每个部门的部门名、工种名和最低工资

SELECT department_name,job_id,MIN(salary)
FROM departments d LEFT JOIN employees e
ON e.`department_id` = d.`department_id`
GROUP BY department_name,job_id

综合练习2

1.简单的分组

案例1:查询每个工种的员工平均工资

SELECT *G(salary),job_id
FROM employees
GROUP BY job_id;

案例2:查询每个位置的部门个数

SELECT COUNT(*),location_id
FROM departments
GROUP BY location_id;

2.可以实现分组前的筛选

案例1:查询邮箱中包含a字符的 每个部门的最高工资

SELECT MAX(salary),department_id
FROM employees
WHERE email LIKE '%a%'
GROUP BY department_id;

案例2:查询有奖金的每个领导手下员工的平均工资

SELECT *G(salary),manager_id
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY manager_id;

3.分组后筛选

案例1:查询哪个部门的员工个数>5

#①查询每个部门的员工个数
SELECT COUNT(*),department_id
FROM employees
GROUP BY department_id;

#② 筛选刚才①结果
SELECT COUNT(*),department_id
FROM employees
GROUP BY department_id
H*ING COUNT(*)>5;

案例2:每个工种有奖金的员工的最高工资>12000的工种编号和最高工资

SELECT job_id,MAX(salary)
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
H*ING MAX(salary)>12000;

案例3:领导编号>102的每个领导手下的最低工资大于5000的领导编号和最低工资

SELECT manager_id,MIN(salary)
FROM employees
GROUP BY manager_id
Where manager_id>102
H*ING MIN(salary)>5000;

4.添加排序

案例:每个工种有奖金的员工的最高工资>6000的工种编号和最高工资,按最高工资升序

SELECT job_id,MAX(salary) m
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
H*ING m>6000
ORDER BY m ;

5.按多个字段分组

案例:查询每个工种每个部门的最低工资,并按最低工资降序

SELECT MIN(salary),job_id,department_id
FROM employees
GROUP BY department_id,job_id
ORDER BY MIN(salary) DESC;

更多编程相关知识,请访问:编程入门!!

以上就是聊聊MySQL中的聚合函数,实践掌握分页查询!的详细内容,更多请关注其它相关文章!


# 聚合函数  # 基础上  # 在这个  # 组中  # 可以使用  # 笛卡尔  # 子句  # 最低工资  # 镜像  # 分页  # 的是  # 分页查询  # MySQL  # 五金营销推广话术技巧  # seo关键词提升排名  # 长春seo规则  # 北京网站建设+招聘信息  # 福建漳州网站建设价格  # 网站推广优化优选  # 广安营销推广公司电话  # seo天启推广  # 酒店网站建设网络推广  # 新开餐厅如何做营销推广 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 优化推广96088 】 【 技术知识133117 】 【 IDC资讯59369 】 【 网络运营7196 】 【 IT资讯61894


相关推荐: 铁路12306买票怎么选双人铺 铁路12306卧铺分配规则说明  《波斯王子:失落的王冠》剑术大师打法攻略  如何测试您的网站全球打开速度-网站海外测速工  cad加载的线型看不见怎么办_cad线型不可见问题解决方法  响应式设计中动态背景颜色条的实现指南  《单词速记宝》设置学习计划方法  Firefox OS应用开发:解决XMLHttpRequest跨域请求阻塞问题  VS Code快捷键when上下文子句的妙用  Excel宏怎么删除_Excel中删除宏的详细操作流程  电脑“无法访问指定设备、路径或文件”怎么办?五种权限设置方法  抖音号显示企业机构号是什么意思?企业机构号申请条件是什么?  Win10显卡驱动安装失败怎么办 Win10使用DDU彻底卸载驱动【解决】  PHP中动态类名访问的类实例类型提示与静态分析实践  《星露谷物语》克林特好感度事件介绍  Cassandra中复合主键、二级索引与ORDER BY排序的限制与解决方案  pubmed数据库官方主页_pubmed学术论文查找官网直达  铁路12306座位怎么选_12306官方选座操作方法  高德地图怎么查看未来行程规划_高德地图未来行程规划查看方法  优化 React onClick 事件处理:函数引用与箭头函数的对比  QQ网页版官方账号登录入口 QQ网页版网页版入口快速导航  铁路12306官网入口 铁路12306中国铁路官网登录首页  荣耀magicv5怎么上手测评  《美篇》取消会员自动续费方法  英国搜索:多数英国人认为语言搜索是未来搜索  PHP魔术方法__set与__isset:设计考量、性能权衡与静态分析的视角  江苏大剧院会员卡购买步骤  德邦快递收费标准详解  sublime怎么快速在浏览器中预览HTML_sublime配置View in Browser教程  Python中深度嵌套字典与列表的数据提取与条件过滤指南  excel怎么计算平均值 excel平均函数*ERAGE使用教学  Win11如何分屏操作_Win11多窗口分屏技巧  优酷下载视频的清晰度怎么选_优酷缓存清晰度设置与选择指南  iPhone14开启Apple TV遥控设置  PHP安全加载非公开目录图片与动态内容类型处理指南  《下一站江湖2》武器获取方法  海棠阅读登录教程_详细讲解海棠登录操作  Microsoft Edge网页字体太淡看不清怎么办_Microsoft Edge字体渲染优化技巧  抖音号升级成企业资质怎么弄?有什么好处?  解决CSS容器溢出问题:使用calc()实现精确布局与边距控制  狙击外星人小游戏在线链接_狙击外星人小游戏网页链接  使用AI在VS Code中将代码从一种语言翻译成另一种  Lar*el Eloquent:高效删除多对多关系中无关联子记录的父模型  电脑没有声音了怎么办 电脑声音问题的全面排查与修复指南【详解】  MacBook Pro词典使用指南  天堂漫画网页版在线阅读 天堂漫画手机版入口  《雷电模拟器》截图方法介绍  火狐浏览器无法自动更新怎么办 手动更新火狐浏览器到最新版本【解决】  谷歌学术论文搜索引擎 谷歌学术官网入口论坛永久链接  如何解决Casbin日志与应用日志不统一的问题,使用casbin/psr3-bridge实现无缝集成  谷歌浏览器如何查找和删除恶意软件 谷歌浏览器内置安全清理工具使用教程 

 2022-01-10

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

运城市盐湖区信雨科技有限公司


运城市盐湖区信雨科技有限公司

运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。

 8156699

 13765294890

 8156699@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.