首页
技术小册
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基础教程(上)
### 章节标题:相对于HAVING子句,更适合写在WHERE子句中的条件 在SQL(Structured Query Language)的广阔世界中,`WHERE`子句与`HAVING`子句都是用于数据过滤的强大工具,但它们各自的应用场景和效率考量却大相径庭。理解何时使用`WHERE`子句、何时更倾向于`HAVING`子句,是优化SQL查询、提升数据库性能的关键步骤。本章节将深入探讨为何在某些情况下,条件更适合写入`WHERE`子句而非`HAVING`子句,并详细解析两者之间的区别与联系。 #### 一、`WHERE`子句与`HAVING`子句的基础认知 **`WHERE`子句**: - `WHERE`子句用于在数据从表中检索出来之前对行进行过滤。它作用于基表或视图,在数据分组(GROUP BY)和聚合(如SUM、AVG、COUNT等)之前执行。 - `WHERE`子句可以包含对列值的直接比较、范围查询、模糊匹配(如LIKE)以及使用逻辑运算符(AND、OR、NOT)组合的条件。 - 它不能直接对聚合函数的结果进行过滤,如不能直接筛选`COUNT(*)`的结果。 **`HAVING`子句**: - `HAVING`子句用于在数据经过`GROUP BY`分组和聚合函数处理后,对分组结果进行过滤。它是对聚合后的结果进行筛选的唯一方式。 - `HAVING`子句可以使用聚合函数作为条件的一部分,如筛选出平均销售额超过某值的部门。 - 需要注意的是,`HAVING`子句也可以包含非聚合条件的过滤,但这样做通常不是最佳实践,因为它会在数据分组和聚合后才进行这些过滤,可能降低查询效率。 #### 二、为何某些条件更适合写在`WHERE`子句中 1. **性能优化** 性能是数据库查询中不可忽视的一环。`WHERE`子句在数据分组和聚合之前执行,意味着它能更早地减少需要处理的数据量,从而可能显著提升查询效率。相比之下,`HAVING`子句在数据已经过分组和聚合后才执行,此时的数据集往往比原始数据小,但过滤操作本身可能因聚合函数的计算而变得复杂和耗时。 例如,假设有一个包含数百万条销售记录的表,如果你想要筛选出特定日期范围内的销售数据,并计算每个部门的总销售额,那么将日期范围条件放在`WHERE`子句中,可以显著减少需要聚合的数据量,提高查询速度。 2. **逻辑清晰性** 从逻辑上讲,`WHERE`子句用于过滤原始数据行,而`HAVING`子句用于过滤聚合后的分组。将能够直接应用于原始数据行的条件放在`WHERE`子句中,有助于保持查询逻辑的清晰性和易于理解。这不仅对于编写查询的开发者来说很重要,也便于后续的维护和调试。 3. **兼容性与标准性** 虽然大多数现代数据库系统都支持`HAVING`子句中使用非聚合条件,但这种做法并不符合SQL标准的初衷,也可能导致不同数据库系统间的兼容性问题。将非聚合条件尽可能放在`WHERE`子句中,可以提高SQL查询的标准化程度,增强其在不同数据库平台上的可移植性。 4. **避免不必要的聚合计算** 在某些情况下,如果条件可以在`WHERE`子句中实现,那么在`HAVING`子句中重复这些条件会导致不必要的聚合计算。比如,如果你已经通过`WHERE`子句过滤掉了大部分不符合条件的行,那么在`HAVING`子句中再次应用相同的条件(尽管可能以聚合函数的形式出现)就是多余的,只会增加数据库的负担。 #### 三、实际案例分析 假设我们有一个名为`sales`的表,包含字段`sale_date`(销售日期)、`department_id`(部门ID)和`amount`(销售额)。 **案例一:筛选特定日期范围内的销售数据** ```sql -- 使用WHERE子句 SELECT department_id, SUM(amount) AS total_sales FROM sales WHERE sale_date BETWEEN '2023-01-01' AND '2023-01-31' GROUP BY department_id; -- 错误示例(使用HAVING,但非最优):虽然技术上可行,但效率较低 SELECT department_id, SUM(amount) AS total_sales FROM sales GROUP BY department_id HAVING MIN(sale_date) >= '2023-01-01' AND MAX(sale_date) <= '2023-01-31'; ``` 在上面的例子中,将日期范围条件放在`WHERE`子句中显然更为高效和直观。 **案例二:筛选销售额超过一定阈值的部门** ```sql -- 正确使用HAVING子句 SELECT department_id, SUM(amount) AS total_sales FROM sales GROUP BY department_id HAVING SUM(amount) > 10000; -- 错误示例(尝试使用WHERE,但不适用于聚合结果) -- SELECT department_id, SUM(amount) AS total_sales -- FROM sales -- WHERE SUM(amount) > 10000 -- 这将导致语法错误 -- GROUP BY department_id; ``` 在这个例子中,由于需要对聚合后的结果进行过滤,因此必须使用`HAVING`子句。 #### 四、总结 综上所述,`WHERE`子句和`HAVING`子句在SQL查询中扮演着不同的角色,各自有其适用的场景。相对于`HAVING`子句,当条件可以直接应用于原始数据行,不涉及聚合函数时,更适合写在`WHERE`子句中。这样做不仅有利于提升查询性能,还能保持查询逻辑的清晰性和标准化程度。在实际应用中,开发者应根据具体需求和数据特点,合理选择使用`WHERE`子句或`HAVING`子句,以达到最优的查询效果。
上一篇:
HAVING子句的构成要素
下一篇:
3-4 对查询结果进行排序
该分类下的相关小册推荐:
SQL基础教程(中)
高性能的Postgres SQL
PostgreSQL入门教程
SQL基础教程(下)