首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
第1章 数据库和SQL
1-1 数据库是什么
我们身边的数据库
为什么DBMS那么重要
DBMS的种类
1-2 数据库的结构
RDBMS的常见系统结构
表的结构
1-3 SQL概要
标准SQL
SQL语句及其种类
SQL的基本书写规则
1-4 表的创建
表的内容的创建
数据库的创建(CREATE DATABASE语句)
表的创建(CREATE TABLE语句)
命名规则
数据类型的指定
约束的设置
1-5 表的删除和更新
表的删除(DROP TABLE语句)
表定义的更新(ALTER TABLE语句)
向Product表中插入数据
第2章 查询基础
2-1 SELECT语句基础
列的查询
查询出表中所有的列
为列设定别名
常数的查询
从结果中删除重复行
根据WHERE语句来选择记录
注释的书写方法
算术运算符
需要注意NULL
比较运算符
对字符串使用不等号时的注意事项
不能对NULL使用比较运算符
2-3 逻辑运算符
NOT运算符
AND运算符和OR运算符
通过括号强化处理
逻辑运算符和真值
含有NULL时的真值
第3章 聚合与排序
3-1 对表进行聚合查询
聚合函数
计算表中数据的行数
计算NULL之外的数据的行数
计算合计值
计算平均值
计算值和小值
使用聚合函数删除重复值(关键字DISTINCT)
3-2 对表进行分组
GROUP BY子句
聚合键中包含NULL的情况
使用WHERE子句时GROUP BY的执行结果
与聚合函数和GROUP BY子句有关的常见错误
3-3 为聚合结果指定条件
HAVING子句
HAVING子句的构成要素
相对于HAVING子句,更适合写在WHERE子句中的条件
3-4 对查询结果进行排序
ORDER BY子句
指定升序或降序
指定多个排序键
NULL的顺序
在排序键中使用显示用的别名
ORDER BY子句中可以使用的列
不要使用列编号
当前位置:
首页>>
技术小册>>
SQL基础教程(上)
小册名称:SQL基础教程(上)
### 3-3 为聚合结果指定条件 在SQL中,聚合函数(如SUM、AVG、MAX、MIN、COUNT等)用于对一组值执行计算,并返回一个单一的值。这些功能在数据分析、报表生成等场景中极为重要。然而,在实际应用中,我们往往需要基于特定的条件来聚合数据,即仅对满足特定条件的记录进行聚合计算。这就是“为聚合结果指定条件”的核心所在。本章节将详细探讨如何在SQL查询中使用`WHERE`子句、`HAVING`子句以及条件表达式来为聚合结果指定条件,并通过实例加深理解。 #### 3.3.1 WHERE子句与聚合查询的误区 首先,需要明确的是,`WHERE`子句虽然常用于在聚合查询之前筛选记录,但它不能直接用于过滤聚合函数的结果。`WHERE`子句作用于聚合前的行级别数据,即它会在数据被聚合之前筛选出满足条件的行。如果你尝试在`WHERE`子句中直接使用聚合函数(如`WHERE SUM(salary) > 10000`),这会导致语法错误,因为聚合函数是在数据行被筛选之后、结果集形成之前计算的。 #### 3.3.2 HAVING子句:为聚合结果指定条件的正确方式 为了解决`WHERE`子句在聚合查询中的局限性,SQL引入了`HAVING`子句。`HAVING`子句允许我们对聚合后的结果进行条件过滤,即它是在数据行被聚合成单个值之后,再对这些聚合值进行筛选的。`HAVING`子句的使用语法与`WHERE`子句类似,但它在逻辑上应用于聚合后的结果集上。 **基本语法**: ```sql SELECT column_name(s), AGGREGATE_FUNCTION(column_name) FROM table_name WHERE condition GROUP BY column_name(s) HAVING condition; ``` **示例**: 假设我们有一个名为`employees`的表,其中包含员工的`department_id`、`salary`等信息,我们想要找出平均薪资超过5000的所有部门的名称及其平均薪资。 ```sql SELECT department_name, AVG(salary) AS average_salary FROM employees GROUP BY department_name HAVING AVG(salary) > 5000; ``` 在这个查询中,我们首先按`department_name`对`employees`表进行分组,然后计算每个部门的平均薪资。最后,`HAVING`子句筛选出那些平均薪资超过5000的部门。 #### 3.3.3 结合使用WHERE和HAVING 在实际应用中,经常需要同时结合使用`WHERE`和`HAVING`子句。`WHERE`子句用于在数据聚合之前过滤掉不满足条件的行,而`HAVING`子句则用于在数据聚合之后过滤掉不满足条件的聚合结果。 **示例**: 继续以上面的`employees`表为例,如果我们想要找出薪资高于3000的员工所在部门中,平均薪资超过5000的部门名称及其平均薪资。 ```sql SELECT department_name, AVG(salary) AS average_salary FROM employees WHERE salary > 3000 -- 在聚合前过滤掉薪资低于3000的员工 GROUP BY department_name HAVING AVG(salary) > 5000; -- 在聚合后过滤掉平均薪资低于5000的部门 ``` 这个查询首先通过`WHERE`子句排除了薪资低于3000的员工,然后按照部门分组并计算平均薪资,最后通过`HAVING`子句进一步筛选出平均薪资超过5000的部门。 #### 3.3.4 注意事项 - **性能考虑**:虽然`HAVING`子句提供了强大的功能,但它可能会对查询性能产生影响,特别是在处理大量数据时。优化查询,如合理使用索引,可以减少查询时间。 - **语法限制**:`HAVING`子句不能与`ORDER BY`子句直接交换位置,因为`HAVING`是在数据聚合之后应用的,而`ORDER BY`则用于对最终结果集进行排序。 - **兼容性**:尽管大多数现代数据库系统都支持`HAVING`子句,但始终建议查阅特定数据库的文档,以确保兼容性和最佳实践。 #### 3.3.5 进阶应用:条件表达式与聚合查询 除了直接使用`HAVING`子句外,还可以将条件表达式与聚合函数结合使用,在`SELECT`列表中实现更复杂的逻辑。例如,可以使用`CASE`语句在聚合查询中计算基于条件的聚合值。 **示例**: 假设我们想要计算`employees`表中每个部门的薪资分布,即薪资在3000至5000之间的员工数、薪资超过5000的员工数。 ```sql SELECT department_name, SUM(CASE WHEN salary BETWEEN 3000 AND 5000 THEN 1 ELSE 0 END) AS mid_salary_count, SUM(CASE WHEN salary > 5000 THEN 1 ELSE 0 END) AS high_salary_count FROM employees GROUP BY department_name; ``` 这个查询利用了`CASE`语句在聚合前为每个薪资区间分配了一个值(1表示在该区间内,0表示不在),然后对这些值进行求和,从而得到了每个部门的薪资分布情况。 综上所述,为聚合结果指定条件是SQL查询中一个重要的高级特性,它允许我们根据特定的业务逻辑来分析和呈现数据。通过合理使用`HAVING`子句和条件表达式,我们可以构建出强大而灵活的查询,以满足复杂的数据分析需求。
上一篇:
与聚合函数和GROUP BY子句有关的常见错误
下一篇:
HAVING子句
该分类下的相关小册推荐:
SQL基础教程(中)
SQL基础教程(下)
PostgreSQL入门教程
高性能的Postgres SQL