【数据库】MySQL聚合统计

目录

1.聚合函数

案例1: 统计班级共有多少同学

 案例2:统计本次考试的数学成绩分数个数

 案例3:统计数学成绩总分

案例4:统计平均总分

案例5:返回英语最高分

案例6:返回 > 70 分以上的数学最低分

2.分组聚合统计(group by)

准备工作:

案例1:如何显示每个部门的平均工资和最高工资

 案例2:显示每个部门的每种岗位的平均工资和最低工资

案例3:显示平均工资低于2000的部门和它的平均工资

那怎么样理解having和where的区别


1.聚合函数

使用聚合函数是为了帮助我们在查询结果之后对结果进行统计,这种统计的方式一般都是一个值为结果。

 在使用这些函数之前,我们需要创建一张测试表

CREATE TABLE exam_result ( 
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, 
name VARCHAR(20) NOT NULL COMMENT '同学姓名', 
chinese float DEFAULT 0.0 COMMENT '语文成绩', 
math float DEFAULT 0.0 COMMENT '数学成绩', 
english float DEFAULT 0.0 COMMENT '英语成绩' 
);

在插入一些数据

INSERT INTO exam_result (name, chinese, math, english) VALUES 
('唐三藏', 67, 98, 56), 
('孙悟空', 87, 78, 77), 
('猪悟能', 88, 98, 90), 
('曹孟德', 82, 84, 67), 
('刘玄德', 55, 85, 45), 
('孙权', 70, 73, 78), 
('宋公明', 75, 65, 30);

 

案例1: 统计班级共有多少同学

 select count(*) from exam_result;

 可以看到它可以直接告诉我们一个值。

也可以对列名进行重命名。

select count(*) 总数 from exam_result;

 案例2:统计本次考试的数学成绩分数个数

先筛选出数学成绩观察

使用函数统计

select count(math) 总数 from exam_result;

可以看到和统计全班人数用法相同。

 我们也可以对重复的数学成绩进行去重之后再统计

select count(distinct math) from exam_result;

 案例3:统计数学成绩总分

使用上面表中的sum函数

select sum(math) from exam_result;

也可以在select之后构建表达式,统计出数学的平均分

select sum(math)/count(*) from exam_result;

案例4:统计平均总分

除了在select之后使用表达式之外,我们还可以使用avg来直接求平均值

 select avg(english+math+chinese) from exam_result;

案例5:返回英语最高分

先查看所有英语成绩

使用max筛选

select max(english) from exam_result;

结果如上

案例6:返回 > 70 分以上的数学最低分

 select min(math) from exam_result where math > 70;

  结果也符合要求。

以上案例我们需要知道的是要被聚合函数统计,被统计的对象一定要是可聚合的,比如上表中的name列和math等成绩列是放不到一起去的 。

2.分组聚合统计(group by)

准备工作:

首先我们需要的目的是分组之后方便进行聚合统计,所以分组的最终目标还是为了聚合统计。

在学习之前我们需要做一些准备工作。

创建一个雇员信息表(来自oracle 9i的经典测试表)

EMP员工表

DEPT部门表

SALGRADE工资等级表。

这里我直接将sql文件的内容放出来

DROP database IF EXISTS `scott`;
CREATE database IF NOT EXISTS `scott` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

USE `scott`;

DROP TABLE IF EXISTS `dept`;
CREATE TABLE `dept` (
  `deptno` int(2) unsigned zerofill NOT NULL COMMENT '部门编号',
  `dname` varchar(14) DEFAULT NULL COMMENT '部门名称',
  `loc` varchar(13) DEFAULT NULL COMMENT '部门所在地点'
);


DROP TABLE IF EXISTS `emp`;
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 '部门编号'
);


DROP TABLE IF EXISTS `salgrade`;
CREATE TABLE `salgrade` (
  `grade` int(11) DEFAULT NULL COMMENT '等级',
  `losal` int(11) DEFAULT NULL COMMENT '此等级最低工资',
  `hisal` int(11) DEFAULT NULL COMMENT '此等级最高工资'
);


insert into dept (deptno, dname, loc)
values (10, 'ACCOUNTING', 'NEW YORK');
insert into dept (deptno, dname, loc)
values (20, 'RESEARCH', 'DALLAS');
insert into dept (deptno, dname, loc)
values (30, 'SALES', 'CHICAGO');
insert into dept (deptno, dname, loc)
values (40, 'OPERATIONS', 'BOSTON');

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7369, 'SMITH', 'CLERK', 7902, '1980-12-17', 800, null, 20);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7499, 'ALLEN', 'SALESMAN', 7698, '1981-02-20', 1600, 300, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7521, 'WARD', 'SALESMAN', 7698, '1981-02-22', 1250, 500, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7566, 'JONES', 'MANAGER', 7839, '1981-04-02', 2975, null, 20);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7654, 'MARTIN', 'SALESMAN', 7698, '1981-09-28', 1250, 1400, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7698, 'BLAKE', 'MANAGER', 7839, '1981-05-01', 2850, null, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7782, 'CLARK', 'MANAGER', 7839, '1981-06-09', 2450, null, 10);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7788, 'SCOTT', 'ANALYST', 7566, '1987-04-19', 3000, null, 20);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7839, 'KING', 'PRESIDENT', null, '1981-11-17', 5000, null, 10);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7844, 'TURNER', 'SALESMAN', 7698,'1981-09-08', 1500, 0, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7876, 'ADAMS', 'CLERK', 7788, '1987-05-23', 1100, null, 20);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7900, 'JAMES', 'CLERK', 7698, '1981-12-03', 950, null, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7902, 'FORD', 'ANALYST', 7566, '1981-12-03', 3000, null, 20);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7934, 'MILLER', 'CLERK', 7782, '1982-01-23', 1300, null, 10);

insert into salgrade (grade, losal, hisal) values (1, 700, 1200);
insert into salgrade (grade, losal, hisal) values (2, 1201, 1400);
insert into salgrade (grade, losal, hisal) values (3, 1401, 2000);
insert into salgrade (grade, losal, hisal) values (4, 2001, 3000);
insert into salgrade (grade, losal, hisal) values (5, 3001, 9999);

这个sql文件的内容都是一些基本的操作,不难看懂。

我们show tables;


可以看到上文创建的表都在其中,接下来我们完成案例上的需求。

案例1:如何显示每个部门的平均工资和最高工资

首先全列查询所有员工的信息

首先我们观察到depton分为三种,也就是说公司分为三个部门10,20 ,30;

所以我们按照需求

select deptno ,max(sal) 最高,avg(sal) 平均 from emp group by deptno;

 我们需要知道的是group by是进行分组聚合统计,所以我们要按照自己觉得需求进行使用。

而且可以看到的是使用group by指定列名,实际分组是通过该列不同行的行数据进行分组的。

其实分组简单地按逻辑来看,就是将一张大表拆成了多个子表,然后对多个子表进行聚合统计

 案例2:显示每个部门的每种岗位的平均工资和最低工资

select deptno,job,avg(sal) 平均工资,min(sal) 最低工资  from emp group by deptno,job;

案例3:显示平均工资低于2000的部门和它的平均工资

我们将问题拆开

1.统计出来每一个部门的平均工资(现将结果聚合出来)

select deptno,avg(sal) 平均工资 from emp group by deptno;

 

2.再进行判断(对聚合出来的结果再进行判断)

这里就要使用having和group by配合使用,对group by结果进行过滤

select deptno,avg(sal) 平均工资 from emp group by deptno having 平均工资<2000;

having的作用是对聚合后的数据再进行统计,也是条件筛选 。

having经常和group by搭配使用,作用是对分组进行筛选,作用有些像where。

那怎么样理解having和where的区别

where和having都可以做条件筛选,但是两个条件筛选完全不同。

如果我们将上文的having换成where

就会报错

 再举一个小例子

可以观察上图中命令的语序 

 所以where是对及具体的任意列进行条件筛选;而having是对分组聚合之后的结果进行条件筛选。

也就是说两个语句的应用场景不同。

where可以对原始的表进行条件过滤,之后在对结果使用having进行分组。

所以我们可以得出结论上图sql语句的执行语句如下

 通过以上的案例,未来我们只要能处理好单表的CURD,之后所有的SQL场景,我们都可以用统一的方式进行。

MySQL数据库统计方法和函数使用丰富多样,以下是一些常见的内容: ### 聚合函数 - **AVG()**:用于计算某列的平均值。例如,要查询学生语文和英语课程的平均分数,可使用以下代码: ```sql -- 查询学生语文科目的平均分数 select course,avg(score) from tb_class where course='语文'; -- 查询学生英语科目的平均分数 select course,avg(score) from tb_class where course='英语'; ``` 此代码通过`avg(score)`计算指定课程的平均分数,依据`course`字段筛选课程[^2]。 - **MAX()**:用于返回某列的最大值。虽然引用中未给出具体示例,但基本使用时可通过`select max(column_name) from table_name;`来获取指定列的最大值。 - **COUNT()**:用于统计记录的数量。如`select count(1) as total from table1 group by period;`,这里使用`count(1)`统计记录数,并通过`group by`按`period`分组,`period`是通过`date_format(date_add(startDate, interval 8 hour), '%u')`计算得出的时间段[^3]。 ### 运算符操作 运算符在统计中也有重要作用,如算术运算符、比较运算符、逻辑运算符和位运算符等。在条件查询、筛选数据等操作中会使用到这些运算符,虽然引用中未详细给出示例,但在实际统计中,可通过运算符筛选出符合条件的数据进行统计。例如,使用比较运算符筛选出分数大于某个值的记录,再进行聚合统计。 ### 分组查询(GROUP BY) 分组查询可将数据按照指定列进行分组,然后对每个组进行统计操作。如`select date_format(date_add(startDate, interval 8 hour), '%u') as period, count(1) as total from table1 group by period;`,将`table1`表中的数据按`period`分组,统计每个分组的记录数[^3]。 ### 排序查询(ORDER BY) 排序查询可对统计结果进行排序。虽然引用中未给出具体示例,但在实际使用中,可在统计查询后添加`order by`语句。例如`select course,avg(score) from tb_class group by course order by avg(score) desc;`,将按课程分组计算平均分数,并按平均分数降序排列。 ### 分页查询(LIMIT) 分页查询用于限制查询结果的数量。例如,要获取前10条统计结果,可使用`select * from (统计查询语句) limit 10;`,虽然引用中未详细示例,但在处理大量统计数据时,分页查询可提高查询效率。 ### 正则表达式 正则表达式可用于筛选符合特定模式的数据。虽然引用中仅提及,但在统计中,可通过正则表达式筛选出特定格式的数据进行统计。例如,筛选出姓名符合某种模式的学生记录进行统计。 ### 日期和时间函数 如引用中的`date_format(date_add(startDate, interval 8 hour), '%u')`,`date_add`用于对日期进行加减操作,`date_format`用于将日期格式化为指定的字符串,在按时间段统计数据时非常有用[^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值