『 MySQL数据库 』聚合统计

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 『 MySQL数据库 』聚合统计



前言 🥑

在MySQL中存在一种查询方式叫做聚合查询;

聚合查询顾名思义就是将一组数据的同种类型进行聚合,那么既然是一组同类型的数据那么即必须要对该数据进行分组同时再对这组数据进行聚合;

所以对于聚合查询来说时应该有两部分组合:

  • 将数据进行分组;
  • 将数据进行聚合统计;
    需要配合SELECT语句进行使用;

🥝 聚合函数

在MySQL中存在一些高频操作:查询数量个数,查询数据总和…

而在MySQL中存在着一些函数,这些函数即用来对表内数据进行这些比较高频的操作,这些函数叫做聚合函数,当然这些函数存在的意义也是聚合查询中的重要操作;

存在一张表(Point):

+----+---------+---------+------+---------+
| id | name    | chinese | math | english |
+----+---------+---------+------+---------+
|  1 | Lihua   |     100 |  118 |     180 |
|  2 | Liming  |      57 |   58 |     140 |
|  3 | Zhaolao |      66 |   80 |      94 |
|  4 | Wu      |      76 |   70 |      94 |
|  5 | Wuqi    |      88 |   43 |     160 |
|  6 | Liqiang |      89 |  122 |     180 |
|  7 | Qinsu   |      90 |  104 |     134 |
|  8 | Zhaoli  |      54 |   74 |     200 |
+----+---------+---------+------+---------+

🍓 COUNT( ) 查询数据数量

语法:

COUNT([DISTINCT] expr) 
-- 返回查询到的数据的数量
-- 其中[]内为可选项

该函数能查询对应数据的数量;

  • 示例1:查询该表中人数个数:
mysql> select count(*) from Point;
+----------+
| count(*) |
+----------+
|        8 |
+----------+
1 row in set (0.00 sec)

  • 示例2:查询该表中math字段数据>100的个数:
mysql> select count(math) from Point where math>100;
+-------------+
| count(math) |
+-------------+
|           3 |
+-------------+
1 row in set (0.00 sec)

  • 示例3:查询该表中english字段数据个数
mysql> select count(distinct english) from Point; -- 利用distinct进行去重
+-------------------------+
| count(distinct english) |
+-------------------------+
|                       6 |
+-------------------------+
1 row in set (0.00 sec)

🍓 SUM( ) 查询数据总和

语法:

COUNT([DISTINCT] expr)

该函数能够算出一组数据的总和;

  • 示例:计算出english字段所有数据的总和:
mysql> select sum(english) from Point;
+--------------+
| sum(english) |
+--------------+
|         1182 |
+--------------+
1 row in set (0.00 sec)
mysql> select sum(distinct english) from Point;
+-----------------------+
| sum(distinct english) |
+-----------------------+
|                   908 |
+-----------------------+
1 row in set (0.00 sec)

🍓 AVG( ) 查询数据平均值

语法:

AVG([DISTINCT] expr)

该函数能够算出一组数据的平均值;

  • 示例:计算出表中english+math+chinese字段的平均值:
mysql> select AVG(english+chinese+math) from Point;
+---------------------------+
| AVG(english+chinese+math) |
+---------------------------+
|                  308.8750 |
+---------------------------+
1 row in set (0.00 sec)

🍓 MAX( ) 查询数据最大值

语法:

MAX([DISTINCT] expr)

该函数能够算出一组数据的最大值;

  • 示例:计算出表中chinese字段的最大值:
mysql> select max(chinese) from Point;
+--------------+
| max(chinese) |
+--------------+
|          100 |
+--------------+
1 row in set (0.00 sec)

🍓 MIN( ) 查询数据最小值

语法:

MIN([DISTINCT] expr)

该函数能够算出一组数据的最小值(用法与MAX()函数相同);


🥝 数据分组GROUP BY子句

聚合统计讲究的是一个先将数据进行分组在将数据进行聚合统计,在MySQL中可以使用GPOUP BY子句将数据进行分组;

在SELECT中使用GROUP BY子句对指定列进行分组查询;

语法:

SELECT column1 ,column2, ... FROM table_name GROUP BY column1,column2...;

在进行聚合查询的演示前需要准备一个来自Oralce 9i的测试用表 - 雇员表(该表在本篇博客中存在资源);

下载该表后使用SOURCE /路径的方式将表至于MySQL当中;

该文件为一个数据库,库中共有三张表: dept部门表,emp员工表,salgrade工资等级表 ;

其中三张表的表结构分别为:

  • dept
Table: dept
Create Table: CREATE TABLE `dept` (
  `deptno` int(2) unsigned zerofill NOT NULL COMMENT ' 部门编号 ',
  `dname` varchar(14) DEFAULT NULL COMMENT ' 部门名称 ',
  `loc` varchar(13) DEFAULT NULL COMMENT ' 部门所在地点 '
) ENGINE=MyISAM DEFAULT CHARSET=utf8

  • emp
Table: emp
Create Table: CREATE TABLE `emp` (
  `empno` int(6) unsigned zerofill NOT NULL COMMENT '雇员编号',
  `ename` varchar(10) DEFAULT NULL COMMENT '雇员姓名',
  `job` varchar(9) DEFAULT NULL COMMENT '雇员职位',
  `mgr` int(4) unsigned zerofill DEFAULT NULL COMMENT '雇员领导编号',
  `hiredate` datetime DEFAULT NULL COMMENT '雇佣时间',
  `sal` decimal(7,2) DEFAULT NULL COMMENT '工资月薪',
  `comm` decimal(7,2) DEFAULT NULL COMMENT '奖金',
  `deptno` int(2) unsigned zerofill DEFAULT NULL COMMENT '部门编号'
) ENGINE=MyISAM DEFAULT CHARSET=utf8

  • salgrade
Table: salgrade
Create Table: CREATE TABLE `salgrade` (
  `grade` int(11) DEFAULT NULL COMMENT '等级',
  `losal` int(11) DEFAULT NULL COMMENT '此等级最低工资',
  `hisal` int(11) DEFAULT NULL COMMENT '此等级最高工资'
) ENGINE=MyISAM DEFAULT CHARSET=utf8

该表的对应数据分别为:

############## 表dept ##############
mysql> select * from dept;
+--------+------------+----------+
| deptno | dname      | loc      |
+--------+------------+----------+
|     10 | ACCOUNTING | NEW YORK |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
+--------+------------+----------+
############## 表emp ##############
mysql> select * from emp;
+--------+--------+-----------+------+---------------------+---------+---------+--------+
| empno  | ename  | job       | mgr  | hiredate            | sal     | comm    | deptno |
+--------+--------+-----------+------+---------------------+---------+---------+--------+
| 007369 | SMITH  | CLERK     | 7902 | 1980-12-17 00:00:00 |  800.00 |    NULL |     20 |
| 007499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 00:00:00 | 1600.00 |  300.00 |     30 |
| 007521 | WARD   | SALESMAN  | 7698 | 1981-02-22 00:00:00 | 1250.00 |  500.00 |     30 |
| 007566 | JONES  | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 |    NULL |     20 |
| 007654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 |     30 |
| 007698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 |    NULL |     30 |
| 007782 | CLARK  | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 |    NULL |     10 |
| 007788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 |    NULL |     20 |
| 007839 | KING   | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |    NULL |     10 |
| 007844 | TURNER | SALESMAN  | 7698 | 1981-09-08 00:00:00 | 1500.00 |    0.00 |     30 |
| 007876 | ADAMS  | CLERK     | 7788 | 1987-05-23 00:00:00 | 1100.00 |    NULL |     20 |
| 007900 | JAMES  | CLERK     | 7698 | 1981-12-03 00:00:00 |  950.00 |    NULL |     30 |
| 007902 | FORD   | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 |    NULL |     20 |
| 007934 | MILLER | CLERK     | 7782 | 1982-01-23 00:00:00 | 1300.00 |    NULL |     10 |
+--------+--------+-----------+------+---------------------+---------+---------+--------+
############## 表salgrade ##############
mysql> select * from salgrade;
+-------+-------+-------+
| grade | losal | hisal |
+-------+-------+-------+
|     1 |   700 |  1200 |
|     2 |  1201 |  1400 |
|     3 |  1401 |  2000 |
|     4 |  2001 |  3000 |
|     5 |  3001 |  9999 |
+-------+-------+-------+

🍓 GROUP BY示例

  1. 显示每个部门的最高工资与平均工资:
    该在示例中需要显示每个每个部门的最高工资,说明需要将 每个部分进行分组,GROUP BY deptno;
    同时要求计算出每个部门的最高工资与最低工资,说明需要对每个部门进行聚合统计,即MAX(sal)AVG(sal);
    将其组合即为:
select max(sal),avg(sal) from emp group by deptno;
  1. 由于是以deptno进行分组,所以可以SELECT出分组的名;
    即:
mysql> select deptno,max(sal),avg(sal) from emp group by deptno;
+--------+----------+-------------+
| deptno | max(sal) | avg(sal)    |
+--------+----------+-------------+
|     10 |  5000.00 | 2916.666667 |
|     20 |  3000.00 | 2175.000000 |
|     30 |  2850.00 | 1566.666667 |
+--------+----------+-------------+

  1. 显示每个部门的每种岗位的平均工资与最低工资:
    在该示例中需要显示每个部门与每种岗位,说明该示例中需要对数据进行两类分组,即为GROUP BY deptno , job;
    且需要聚合统计出该类数据的平均值与最高值,即为AVG(sal)MIN(sal);
    在该条件中由于是对部门deptno与岗位job进行分组,所以在SELECT时可以分别显示出他们的值;
    即为:
mysql> SELECT deptno,job,avg(sal),min(sal) from emp group by deptno,job;
+--------+-----------+-------------+----------+
| deptno | job       | avg(sal)    | min(sal) |
+--------+-----------+-------------+----------+
|     10 | CLERK     | 1300.000000 |  1300.00 |
|     10 | MANAGER   | 2450.000000 |  2450.00 |
|     10 | PRESIDENT | 5000.000000 |  5000.00 |
|     20 | ANALYST   | 3000.000000 |  3000.00 |
|     20 | CLERK     |  950.000000 |   800.00 |
|     20 | MANAGER   | 2975.000000 |  2975.00 |
|     30 | CLERK     |  950.000000 |   950.00 |
|     30 | MANAGER   | 2850.000000 |  2850.00 |
|     30 | SALESMAN  | 1400.000000 |  1250.00 |
+--------+-----------+-------------+----------+
9 rows in set (0.00 sec)
# 也可将其进行重命名
mysql> SELECT deptno 部门,job 岗位,avg(sal) 最大工资,min(sal) 最小工资 from emp group by deptno,job;
+--------+-----------+--------------+--------------+
| 部门   | 岗位      | 最大工资     | 最小工资     |
+--------+-----------+--------------+--------------+
|     10 | CLERK     |  1300.000000 |      1300.00 |
|     10 | MANAGER   |  2450.000000 |      2450.00 |
|     10 | PRESIDENT |  5000.000000 |      5000.00 |
|     20 | ANALYST   |  3000.000000 |      3000.00 |
|     20 | CLERK     |   950.000000 |       800.00 |
|     20 | MANAGER   |  2975.000000 |      2975.00 |
|     30 | CLERK     |   950.000000 |       950.00 |
|     30 | MANAGER   |  2850.000000 |      2850.00 |
|     30 | SALESMAN  |  1400.000000 |      1250.00 |
+--------+-----------+--------------+--------------+
9 rows in set (0.00 sec)

🍓 HAVING语句

HAVING语句为条件筛选语句的一种,其使用方式类似于WHERE;

大部分情况下HAVING子句是用来配合GROUP BY语句进行使用,即对分组聚合后的数据进行筛选;

HAVING子句可以做到与WHERE子句一样的事,但是WHERE子句的功能却不能与HAVING子句相当;

由于HAVING语句是用来针对聚合统计而产生的,所以在MySQL中不能使用HAVING子句来代替WHERE子句,即这两个语句不能混为一谈;

  • 示例:显示平均工资低于2000的部门和它的平均工资:
    在该示例中要求了平均工资低于2000的部门,即需要对部门进行GROUP BY分类,即GROUP BY deptno;
    同时示例要求显示平均工资,即为AVG(sal);
    将其组合在一起即能显示出各个部门的平均工资:
mysql> select deptno,avg(sal) from emp group by deptno;
+--------+-------------+
| deptno | avg(sal)    |
+--------+-------------+
|     10 | 2916.666667 |
|     20 | 2175.000000 |
|     30 | 1566.666667 |
+--------+-------------+
3 rows in set (0.00 sec)
  • 其又要求显示平均工资低于2000的部门与它的平均工资,则可以使用HAVING子句对聚合统计后的数据进行筛选;
mysql> select deptno as 部门,avg(sal) as 平均工资  from emp group by deptno having 平均工资<2000;
+--------+--------------+
| 部门   | 平均工资     |
+--------+--------------+
|     30 |  1566.666667 |
+--------+--------------+
1 row in set (0.00 sec)
##当使用where子句代替having子句时将会报错;
mysql> select deptno as 部门,avg(sal) as 平均工资  from emp group by deptno where 平均工资<2000;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where 平均工资<2000' at line 1


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
6月前
|
存储 SQL 关系型数据库
轻松入门MySQL:加速进销存!利用MySQL存储过程轻松优化每日销售统计(15)
轻松入门MySQL:加速进销存!利用MySQL存储过程轻松优化每日销售统计(15)
162 0
|
6月前
|
SQL 关系型数据库 MySQL
mysql一条sql查询出多个统计结果
mysql一条sql查询出多个统计结果
58 0
|
5天前
|
SQL NoSQL 关系型数据库
2024Mysql And Redis基础与进阶操作系列(5)作者——LJS[含MySQL DQL基本查询:select;简单、排序、分组、聚合、分组、分页等详解步骤及常见报错问题所对应的解决方法]
MySQL DQL基本查询:select;简单、排序、分组、聚合、分组、分页、INSERT INTO SELECT / FROM查询结合精例等详解步骤及常见报错问题所对应的解决方法
|
5天前
|
SQL NoSQL 关系型数据库
|
6月前
|
缓存 关系型数据库 数据库
关系型数据库高效查询和统计
【5月更文挑战第8天】关系型数据库高效查询和统计
81 7
|
19天前
|
SQL 存储 关系型数据库
mysql 数据库空间统计sql
mysql 数据库空间统计sql
37 0
|
4月前
|
SQL 数据库 关系型数据库
MySQL设计规约问题之为什么统计表中记录数时推荐使用COUNT(*)而不是COUNT(primary_key)或COUNT(1)
MySQL设计规约问题之为什么统计表中记录数时推荐使用COUNT(*)而不是COUNT(primary_key)或COUNT(1)
|
5月前
|
Oracle 关系型数据库 MySQL
深入了解 Linux 命令 `db_stat`:数据库统计信息的获取
本文模拟了 Linux 环境下使用 `db_stat` 命令获取数据库统计信息的场景,实际上`db_stat`是特定数据库系统的自定义工具。文章通过示例展示了如何针对Oracle、PostgreSQL和MySQL使用各自内置命令收集统计信息,强调了权限、性能影响和数据实时性等因素,并指出这些信息对优化数据库管理至关重要。
|
6月前
|
存储 关系型数据库 MySQL
【MySQL探索之旅】数据库设计以及聚合查询
【MySQL探索之旅】数据库设计以及聚合查询
|
6月前
|
Oracle 关系型数据库 MySQL
【MySQL】8. 基本查询(update/delete/聚合/分组)
【MySQL】8. 基本查询(update/delete/聚合/分组)
58 0