导读:本期聚焦于小伙伴创作的《SQL报表查询中HAVING过滤速度慢怎么办?HAVING改写WHERE有哪些实用技巧》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《SQL报表查询中HAVING过滤速度慢怎么办?HAVING改写WHERE有哪些实用技巧》有用,将其分享出去将是对创作者最好的鼓励。

在SQL报表开发中,HAVING子句常用于对分组后的结果进行过滤,但不少开发者发现当数据量较大时,使用HAVING过滤的查询耗时远高于预期,甚至出现查询超时的情况。这是因为HAVING的执行时机和WHERE存在本质差异,不合理的用法会直接导致性能损耗。

SQL报表查询中HAVING过滤速度慢怎么办?HAVING改写WHERE有哪些实用技巧

HAVING过滤慢的核心原因

要理解HAVING过滤慢的问题,首先需要明确SQL查询的执行顺序:FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY。从这个顺序可以看出,WHERE是在分组之前执行过滤,而HAVING是在分组完成之后才执行过滤。

这意味着如果过滤条件不需要依赖分组后的聚合结果,使用HAVING的话,数据库会先完成所有数据的分组操作,再对分组后的结果进行过滤,相当于处理了更多无用的数据,自然会带来性能损耗。而WHERE可以在分组前就过滤掉不符合条件的数据,减少后续分组操作的数据量。

HAVING与WHERE的核心差异

两者的核心差异主要体现在执行时机和可用条件上,具体对比如下:

对比维度WHEREHAVING
执行时机分组之前分组之后
可用条件普通字段过滤条件,不能使用聚合函数可以使用聚合函数作为过滤条件
数据过滤范围原始数据行分组后的结果集
性能表现通常更优,可减少分组数据量分组后过滤,数据量大时性能较差

HAVING改写WHERE的实用技巧

技巧1:普通字段过滤条件前置到WHERE

如果HAVING中的过滤条件不涉及聚合函数,只是普通字段的筛选,直接把条件移到WHERE子句中即可。比如下面这个统计每个部门薪资总和的查询,原本用HAVING过滤部门编号:

-- 优化前的查询,HAVING过滤普通字段
SELECT dept_id, SUM(salary) AS total_salary
FROM employee
GROUP BY dept_id
HAVING dept_id IN (10, 20, 30);

优化后把部门过滤条件放到WHERE中,分组前就过滤掉不需要的部门数据:

-- 优化后的查询,WHERE前置过滤
SELECT dept_id, SUM(salary) AS total_salary
FROM employee
WHERE dept_id IN (10, 20, 30)
GROUP BY dept_id;

技巧2:聚合条件拆分前置过滤

如果HAVING的过滤条件涉及聚合函数,但部分数据可以通过前置条件过滤,可以先在WHERE中过滤掉不可能满足聚合条件的数据。比如要查询平均薪资大于5000的部门,原本的查询是:

-- 优化前的查询
SELECT dept_id, AVG(salary) AS avg_salary
FROM employee
GROUP BY dept_id
HAVING AVG(salary) > 5000;

如果员工薪资最高不超过10000,那么单个员工薪资小于等于2500的部门,平均薪资肯定不可能超过5000,就可以先在WHERE中过滤掉这些员工数据:

-- 优化后的查询,前置过滤低薪资员工
SELECT dept_id, AVG(salary) AS avg_salary
FROM employee
WHERE salary > 2500
GROUP BY dept_id
HAVING AVG(salary) > 5000;

技巧3:使用子查询拆分聚合逻辑

对于复杂的聚合过滤场景,可以把聚合计算放到子查询中,外层用WHERE过滤。比如要查询总订单金额大于10000的用户,原本的查询是:

-- 优化前的查询
SELECT user_id, SUM(order_amount) AS total_amount
FROM order_table
GROUP BY user_id
HAVING SUM(order_amount) > 10000;

优化后先通过子查询计算每个用户的订单总金额,外层再用WHERE过滤:

-- 优化后的查询,子查询拆分逻辑
SELECT user_id, total_amount
FROM (
    SELECT user_id, SUM(order_amount) AS total_amount
    FROM order_table
    GROUP BY user_id
) AS temp
WHERE total_amount > 10000;

改写时的注意事项

并不是所有HAVING都可以改写成WHERE,只有当过滤条件不依赖分组后的聚合结果时,改写才有效。如果过滤条件必须使用聚合函数的结果,比如HAVING COUNT(*) > 5这种统计行数的条件,就无法直接移到WHERE中,此时可以考虑通过索引优化、减少分组数据量等方式提升性能。

另外改写后需要验证查询结果是否和原查询一致,避免出现过滤逻辑偏差导致数据错误。可以在测试环境对比改写前后的查询结果和数据量,确认无误后再应用到生产环境。

SQLHAVINGWHERE报表查询查询优化修改时间:2026-07-09 07:30:30

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。