MySQL中数据聚合函数

本文介绍了SQL中聚合函数如何处理NULL值,包括COUNT、SUM、AVG等函数的行为,并通过实例展示了带WHERE条件的聚合操作及分组聚合的使用。

-- 聚合函数中null的处理,建立一个test1 表


create table test1(
id int primary key auto_increment,
name varchar(20)
);

-- 向test1表中输入数据ABCD和四个空
insert into test1(name) values
('A'),('B'),('C'),('D'),
(Null),(Null),(Null),(Null);

select count(*) from test1;           --4条
select count(name) from test1;   -- 4条,因为null不算
select count(null) from test1;      -- 0条,全是字符全部被null替换

-- 在sum/avg/max/min遇到null(包含其他非数字字段),值会视为0,聚合的时候就不考虑这些了

-- 建立一个test2表
create table test2(
id int primary key auto_increment,
name int(20)
);

-- 向test2表中输入数据
insert into test2(name) values
('1'),('2'),('3'),('4'),
(Null),(Null),(Null),(Null);

select sum(name) from test2;    -- 求和1+2+3+4=10
select avg(name) from test2;     -- 求平均值2.5
select max(name) from test2;    -- 求最大值4
select min(name) from test2;     --求最小值1

-- 符合规则:有null参与的表达式


select count(age+null) from students;     -- 0
-- 因为  count(age + null)  视为 count( null )  了。

-- 带where条件的聚合,首先进行where条件的筛选,再进行聚合

-- 建立students表,并向其中输入数据

create table students(
id int primary key auto_increment,
name varchar(20) not null,
age int not null,
gender varchar(1) not null
);

insert into students(name,age,gender) values
('小红','1','女'),
('小蓝','1','男'),
('小刚','2','男'),
('小黄','2','女'),
('小橙','3','女');

select count(*) from students;                                   -- 所有结果
select count(*) from students where gender='女';     -- 性别为女的人数
select count(*) from students where gender='男';     -- 性别为男的人数
select count(*) from students where age>1;             -- id大于1的人数(我忘了,求大神指点)
select count(age)from students where age>2;         -- age大于2的人数
select sum(age) from students where age>2;          -- age>2的age求和

-- 分组聚合

-- 按性别进行分类

-- 由于5行数据中,gender字段的值只有两个
select count(*) from students group by gender;

-- 聚合查询的select后边,可以出现两种东西:聚合函数、分组聚合时间、分组的依据字段
-- gender作为分组凭证,可以出现在select后面,所以有
select gender,count(*) from students group by gender;
select name,count(*) from studentd;-- 错误用法

-- 分组凭证可以是字段,也可以是表达式
select age % 2 as 奇偶性,count(*) from students group by age%2;
select age % 2 as 奇偶性,count(*) from students group by 奇偶性;
-- 可以同时以多个表达式作为分组
select age % 2 as 奇偶性,gender,count(*) from students group by gender,奇偶性;

select age,count(*) from students group by age;

-- 从分组聚合的结果中,再进行一次聚合:having语句
select * from students;
select * from students where age <= 2;
select age , count(*) from students where age <= 2 group by age;
select age , count(*) from students where age <= 1 group by age having count(*) =1;
select age , count(*) from students where age <= 1 group by age having count(*) =1 order by age limit 1 offset 0;
 

<think>我们被要求回答关于MySQL支持的聚合函数的问题。根据引用内容,我们知道聚合函数包括COUNT(), SUM(), AVG(), MAX(), MIN(),以及引用[4]中提到的GROUP_CONCAT()。此外,引用[5]中出现了SUM()和AVG(),但没有新的聚合函数。因此,我们可以总结常见的聚合函数,并补充其他MySQL支持的聚合函数MySQL支持的聚合函数包括但不限于以下: 1. COUNT():计算行数。 2. SUM():计算数值列的总和。 3. AVG():计算数值列的平均值。 4. MAX():返回列的最大值。 5. MIN():返回列的最小值。 6. GROUP_CONCAT():将来自多个行的字符串连接成一个字符串(引用[4]提到)。 此外,MySQL还支持以下聚合函数: - BIT_AND():返回所有比特位的按位与。 - BIT_OR():返回所有比特位的按位或。 - BIT_XOR():返回所有比特位的按位异或。 - STD():计算总体标准差。 - STDDEV_POP():计算总体标准差(同STD())。 - STDDEV_SAMP():计算样本标准差。 - VAR_POP():计算总体方差。 - VAR_SAMP():计算样本方差。 注意:引用[2]和[3]都提到不能在WHERE子句中使用聚合函数,这是因为聚合函数是在GROUP BY子句之后进行计算的,而WHERE子句是在分组之前进行过滤。因此,如果要对聚合结果进行过滤,应该使用HAVING子句。 下面我们按照要求组织回答: ### MySQL支持的聚合函数详解 在MySQL中,聚合函数用于对一组值执行计算并返回单一的值。它们通常与`GROUP BY`子句结合使用,用于对数据进行分组汇总[^1]。以下是MySQL中常用的聚合函数及其说明: #### 1. 基本聚合函数 1. **`COUNT()`** - 功能:统计行数或非NULL值的数量。 - 示例: ```sql SELECT COUNT(*) FROM employees; -- 统计所有行数 SELECT COUNT(department_id) FROM employees; -- 统计非NULL的department_id数量 ``` 2. **`SUM()`** - 功能:计算数值列的总和。 - 示例: ```sql SELECT SUM(salary) FROM employees; -- 计算所有员工工资总和 ``` 3. **`AVG()`** - 功能:计算数值列的平均值。 - 示例: ```sql SELECT AVG(salary) FROM employees; -- 计算平均工资 ``` 4. **`MAX()`** - 功能:返回列的最大值。 - 示例: ```sql SELECT MAX(salary) FROM employees; -- 获取最高工资 ``` 5. **`MIN()`** - 功能:返回列的最小值。 - 示例: ```sql SELECT MIN(salary) FROM employees; -- 获取最低工资 ``` #### 2. 字符串聚合函数 6. **`GROUP_CONCAT()`** - 功能:将来自多个行的字符串连接成一个字符串,可指定分隔符(默认逗号)[^4]。 - 示例: ```sql SELECT department_id, GROUP_CONCAT(name SEPARATOR '; ') FROM employees GROUP BY department_id; -- 将同一部门的员工姓名用分号连接 ``` #### 3. 统计聚合函数 7. **`STD()` 或 `STDDEV_POP()`** - 功能:计算总体标准差。 - 示例: ```sql SELECT STD(salary) FROM employees; -- 计算工资的总体标准差 ``` 8. **`STDDEV_SAMP()`** - 功能:计算样本标准差。 - 示例: ```sql SELECT STDDEV_SAMP(salary) FROM employees; -- 计算工资的样本标准差 ``` 9. **`VAR_POP()`** - 功能:计算总体方差。 - 示例: ```sql SELECT VAR_POP(salary) FROM employees; -- 计算工资的总体方差 ``` 10. **`VAR_SAMP()`** - 功能:计算样本方差。 - 示例: ```sql SELECT VAR_SAMP(salary) FROM employees; -- 计算工资的样本方差 ``` #### 4. 位运算聚合函数 11. **`BIT_AND()`** - 功能:返回所有比特位的按位与。 - 示例: ```sql SELECT BIT_AND(flags) FROM permissions; -- 计算flags列的按位与 ``` 12. **`BIT_OR()`** - 功能:返回所有比特位的按位或。 - 示例: ```sql SELECT BIT_OR(flags) FROM permissions; -- 计算flags列的按位或 ``` 13. **`BIT_XOR()`** - 功能:返回所有比特位的按位异或。 - 示例: ```sql SELECT BIT_XOR(flags) FROM permissions; -- 计算flags列的按位异或 ``` ### 使用注意事项 - **聚合函数与`GROUP BY`**:当使用聚合函数时,通常需要配合`GROUP BY`子句对数据进行分组。如果省略`GROUP BY`,则整个表作为一组。 - **过滤聚合结果**:不能在`WHERE`子句中使用聚合函数,因为`WHERE`在聚合前执行。若要对聚合结果过滤,应使用`HAVING`子句[^2][^3]。 错误示例: ```sql SELECT department_id, AVG(salary) FROM employees WHERE AVG(salary) > 8000 -- 错误!WHERE不能使用聚合函数 GROUP BY department_id; ``` 正确写法: ```sql SELECT department_id, AVG(salary) FROM employees GROUP BY department_id HAVING AVG(salary) > 8000; -- 使用HAVING过滤分组结果 ``` - **处理NULL值**:大多数聚合函数(如`SUM()`、`AVG()`)会忽略NULL值,但`COUNT(列名)`也会忽略NULL值,而`COUNT(*)`不会。 ### 性能优化建议 - **索引优化**:在聚合列上创建索引可加速`MIN()`、`MAX()`、`COUNT(DISTINCT)`等操作。 - **避免全表扫描**:使用`WHERE`子句提前过滤数据,减少参与聚合数据量。 ```mermaid graph TD A[执行查询] --> B[WHERE子句过滤] B --> C[GROUP BY分组] C --> D[聚合函数计算] D --> E[HAVING过滤] E --> F[返回结果] ``` ### 总结 MySQL提供了丰富的聚合函数,涵盖统计、字符串处理、位运算等场景。合理使用这些函数可高效完成数据汇总分析任务,但需注意`WHERE`与`HAVING`的区别[^2][^3],以及性能优化要点。 §§相关问题§§ 1. MySQL中`COUNT(1)`、`COUNT(*)`和`COUNT(列名)`有什么区别? 2. 如何在MySQL中使用`HAVING`子句对聚合结果进行过滤? 3. 聚合函数在计算时如何处理NULL值?</think>### MySQL 支持的聚合函数详解 在 MySQL 中,聚合函数用于对一组值进行计算并返回单个汇总值,是数据分析和统计的核心工具。以下是 MySQL 支持的常用聚合函数及其详细说明: --- #### 1. **`COUNT()`** [^1] - **功能**:统计行数或非 NULL 值的数量 - **使用场景**: ```sql -- 统计总行数 SELECT COUNT(*) FROM employees; -- 统计非 NULL 的部门 ID 数量 SELECT COUNT(department_id) FROM employees; -- 统计不同部门数量 SELECT COUNT(DISTINCT department_id) FROM employees; ``` --- #### 2. **`SUM()`** [^1][^5] - **功能**:计算数值列的总和 - **使用场景**: ```sql -- 计算工资总和 SELECT SUM(salary) FROM employees; -- 按部门分组计算工资总和 SELECT department_id, SUM(salary) FROM employees GROUP BY department_id; ``` --- #### 3. **`AVG()`** [^1][^2][^5] - **功能**:计算数值列的平均值 - **使用场景**: ```sql -- 计算平均工资 SELECT AVG(salary) FROM employees; -- 按部门分组计算平均工资 SELECT department_id, AVG(salary) FROM employees GROUP BY department_id; -- 等效计算(SUM/COUNT) SELECT SUM(salary)/COUNT(salary) FROM employees; -- 忽略 NULL 值 [^5] ``` --- #### 4. **`MAX()`** [^1] - **功能**:返回列的最大值 - **使用场景**: ```sql -- 获取最高工资 SELECT MAX(salary) FROM employees; -- 获取每个部门的最高工资 SELECT department_id, MAX(salary) FROM employees GROUP BY department_id; ``` --- #### 5. **`MIN()`** [^1] - **功能**:返回列的最小值 - **使用场景**: ```sql -- 获取最低工资 SELECT MIN(salary) FROM employees; -- 获取每个部门的最低工资 SELECT department_id, MIN(salary) FROM employees GROUP BY department_id; ``` --- #### 6. **`GROUP_CONCAT()`** [^4] - **功能**:将多行字符串连接为单个字符串 - **使用场景**: ```sql -- 将同一部门的员工姓名连接为字符串 SELECT department_id, GROUP_CONCAT(name SEPARATOR '; ') FROM employees GROUP BY department_id; ``` --- #### 7. **统计函数** - **`STD()` / `STDDEV()`**:计算总体标准差 - **`VARIANCE()`**:计算总体方差 - **使用场景**: ```sql SELECT STD(salary) FROM employees; -- 工资标准差 SELECT VARIANCE(salary) FROM employees; -- 工资方差 ``` --- ### ⚠️ 重要注意事项 1. **`WHERE` 子句限制** 聚合函数**不能**直接用于 `WHERE` 子句[^2][^3]: ```sql -- 错误示例(非法使用) SELECT department_id, AVG(salary) FROM employees WHERE AVG(salary) > 8000 -- 报错! GROUP BY department_id; -- 正确写法(改用 HAVING) SELECT department_id, AVG(salary) FROM employees GROUP BY department_id HAVING AVG(salary) > 8000; -- 对聚合结果过滤 ``` 2. **`NULL` 值处理** 聚合函数自动忽略 `NULL` 值: ```sql -- 若 commission_pct 有 NULL 值 SELECT AVG(commission_pct) -- 只计算非 NULL 值 FROM employees; ``` 3. **与 `GROUP BY` 的配合** 非聚合字段必须包含在 `GROUP BY` 中: ```sql -- 正确分组 SELECT department_id, COUNT(*) FROM employees GROUP BY department_id; -- 错误示例(缺少分组) SELECT department_id, salary -- salary 未分组 FROM employees; ``` --- ### 执行流程 ```mermaid graph LR A[原始数据] --> B[WHERE 过滤] B --> C[GROUP BY 分组] C --> D[聚合计算] D --> E[HAVING 过滤] E --> F[返回结果] ``` --- ### 性能优化建议 1. **索引优化** 在聚合列(如 `salary`)和分组列(如 `department_id`)上创建索引 2. **减少数据量** 先用 `WHERE` 过滤再聚合: ```sql SELECT department_id, AVG(salary) FROM employees WHERE hire_date > '2020-01-01' -- 先过滤 GROUP BY department_id; ``` 3. **避免全表扫描** 对大表使用 `LIMIT` 采样分析: ```sql SELECT AVG(salary) FROM employees LIMIT 10000; ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值