首页 > 数据库 > SQL > 正文

sql怎样使用having结合聚合函数筛选数据 sql聚合筛选与having用法的技巧

爱谁谁
发布: 2025-08-19 08:28:01
原创
637人浏览过
HAVING用于筛选分组后的聚合结果,WHERE用于过滤分组前的原始行数据;执行顺序上WHERE先于GROUP BY,HAVING在GROUP BY之后,二者可结合使用以提升查询效率。

sql怎样使用having结合聚合函数筛选数据 sql聚合筛选与having用法的技巧

HAVING
登录后复制
子句在SQL中,是专门用来筛选经过
GROUP BY
登录后复制
分组后的数据。它与
WHERE
登录后复制
子句不同,
WHERE
登录后复制
在数据分组之前对单行记录进行筛选,而
HAVING
登录后复制
则是在聚合函数(如
COUNT()
登录后复制
,
SUM()
登录后复制
,
AVG()
登录后复制
,
MAX()
登录后复制
,
MIN()
登录后复制
)计算出结果之后,再对这些聚合结果进行条件过滤。简单来说,如果你想基于某个总和、平均值或数量来筛选组,那就用
HAVING
登录后复制

解决方案

使用

HAVING
登录后复制
结合聚合函数筛选数据,其核心在于理解SQL查询的执行顺序。它总是在
GROUP BY
登录后复制
之后执行。基本语法结构是这样的:

SELECT
    column1,
    aggregate_function(column2)
FROM
    table_name
GROUP BY
    column1
HAVING
    aggregate_function(column2) [comparison_operator] value;
登录后复制

举个例子,假设我们有一个

orders
登录后复制
表,里面有
customer_id
登录后复制
amount
登录后复制
字段。我们想找出那些总订单金额超过1000的客户。

SELECT
    customer_id,
    SUM(amount) AS total_spent
FROM
    orders
GROUP BY
    customer_id
HAVING
    SUM(amount) > 1000;
登录后复制

这里,

SUM(amount)
登录后复制
是一个聚合函数,它计算了每个客户的总金额。
HAVING SUM(amount) > 1000
登录后复制
则是在这些总金额计算出来之后,筛选出那些总金额大于1000的客户。如果没有
HAVING
登录后复制
,我们是无法直接在
WHERE
登录后复制
子句中使用
SUM(amount)
登录后复制
的,因为
WHERE
登录后复制
是在行级别操作的。

HAVING与WHERE子句有何本质区别?何时选用它们?

这真的是SQL初学者,甚至是一些有经验的开发者都会偶尔混淆的点。我个人觉得,理解它们的执行时机是关键。

WHERE
登录后复制
子句,它就像是数据进入厨房前的第一道关卡,负责对每一份食材(每一行数据)进行检查,不符合条件的直接剔除,连锅都不让进。它作用于原始的、未聚合的行数据。所以,你不能在
WHERE
登录后复制
里直接用
COUNT()
登录后复制
SUM()
登录后复制
这类聚合函数,因为那时候数据还没“聚”起来。

HAVING
登录后复制
呢,它更像是菜肴出锅前的最后一道品控。当所有食材都经过烹饪(
GROUP BY
登录后复制
分组和聚合函数计算)变成了最终的菜品(聚合结果)后,
HAVING
登录后复制
才开始工作,检查这些“菜品”是否符合标准。比如,你做了一桌菜,
HAVING
登录后复制
会说:“这盘菜如果总重量小于500克,就不能上桌!”它看的是整体,是聚合后的结果。

什么时候用哪个?

  • WHERE
    登录后复制
    当你需要基于原始行数据进行筛选时。比如,只统计“活跃”用户的订单,或者只考虑“2023年”的销售数据。这些条件都不依赖于聚合结果。

    -- 找出2023年单笔订单金额超过100的所有订单
    SELECT order_id, customer_id, amount
    FROM orders
    WHERE order_date BETWEEN '2023-01-01' AND '2023-12-31'
    AND amount > 100;
    登录后复制
  • HAVING
    登录后复制
    当你的筛选条件依赖于聚合函数的结果时。比如,找出平均销售额超过某个数值的地区,或者至少有5个订单的客户。

    -- 找出平均订单金额超过200的客户
    SELECT customer_id, AVG(amount) AS avg_order_amount
    FROM orders
    GROUP BY customer_id
    HAVING AVG(amount) > 200;
    登录后复制

有时候,两者甚至会一起出现。比如,我们想找出2023年那些总订单金额超过1000的客户。这时,先用

WHERE
登录后复制
筛选出2023年的订单,再用
GROUP BY
登录后复制
HAVING
登录后复制
来聚合和筛选。

SELECT
    customer_id,
    SUM(amount) AS total_spent
FROM
    orders
WHERE
    order_date BETWEEN '2023-01-01' AND '2023-12-31' -- 先筛选2023年的订单
GROUP BY
    customer_id
HAVING
    SUM(amount) > 1000; -- 再筛选总金额大于1000的客户
登录后复制

这种组合使用非常常见,也是写出高效且精确SQL的关键。

结合多个聚合函数或条件在HAVING中进行筛选的实际场景

HAVING
登录后复制
子句的强大之处在于,它不仅限于一个简单的聚合条件。你可以像在
WHERE
登录后复制
子句中那样,使用
AND
登录后复制
OR
登录后复制
NOT
登录后复制
等逻辑运算符来组合多个聚合条件,甚至结合多个不同的聚合函数进行筛选。这在处理复杂的业务逻辑时显得尤为有用。

想象一个场景:我们想找出那些平均订单金额超过500,并且总订单数至少有3个的客户。

SELECT
    customer_id,
    AVG(amount) AS avg_order_amount,
    COUNT(order_id) AS total_orders
FROM
    orders
GROUP BY
    customer_id
HAVING
    AVG(amount) > 500 AND COUNT(order_id) >= 3;
登录后复制

在这个例子中,我们同时使用了

AVG()
登录后复制
COUNT()
登录后复制
这两个聚合函数,并在
HAVING
登录后复制
子句中用
AND
登录后复制
将它们的条件连接起来。只有同时满足这两个条件的客户才会被返回。

聚好用AI
聚好用AI

可免费AI绘图、AI音乐、AI视频创作,聚集全球顶级AI,一站式创意平台

聚好用AI 115
查看详情 聚好用AI

再来一个稍微复杂点的:找出那些总销售额超过10000,或者虽然总销售额没到10000但至少有100笔交易的商品。

SELECT
    product_id,
    SUM(sale_amount) AS total_sales,
    COUNT(transaction_id) AS total_transactions
FROM
    sales_records
GROUP BY
    product_id
HAVING
    SUM(sale_amount) > 10000 OR COUNT(transaction_id) >= 100;
登录后复制

这种灵活性让

HAVING
登录后复制
成为处理报表和数据分析中“基于汇总数据进行筛选”任务的利器。你可能会发现,很多时候业务部门提的需求,最终落实到SQL上,都需要
HAVING
登录后复制
来完成这种多维度、基于聚合结果的筛选。

在SQL查询优化中,HAVING的使用有哪些值得注意的地方?

谈到优化,

HAVING
登录后复制
的使用确实有一些值得我们思考的地方。我经常会看到一些查询,明明可以在
WHERE
登录后复制
子句中完成的筛选,却被放到了
HAVING
登录后复制
里。虽然结果可能一样,但性能上却可能大相径庭。

核心原则是:能用

WHERE
登录后复制
的,就不要用
HAVING
登录后复制

为什么这么说?因为

WHERE
登录后复制
子句在数据分组和聚合之前就对数据进行了过滤。这意味着它减少了需要处理的行数,从而减轻了
GROUP BY
登录后复制
和聚合函数的工作量。如果你的原始数据集非常庞大,先用
WHERE
登录后复制
过滤掉大量不相关的行,那么后续的聚合操作就会快很多。

举个例子:我们只想分析2023年的数据,并且找出总金额超过1000的客户。

低效的做法(尽量避免,如果条件可以下推到WHERE):

SELECT
    customer_id,
    SUM(amount) AS total_spent
FROM
    orders
GROUP BY
    customer_id
HAVING
    SUM(amount) > 1000
    AND MAX(order_date) >= '2023-01-01' -- 这里尝试用HAVING过滤年份,但效率不如WHERE
    AND MIN(order_date) <= '2023-12-31';
登录后复制

这里,

MAX(order_date)
登录后复制
MIN(order_date)
登录后复制
是聚合函数,所以它们必须在
HAVING
登录后复制
里。但如果目的只是筛选2023年的订单,那么在
WHERE
登录后复制
里直接过滤
order_date
登录后复制
列会更高效。

高效的做法:

SELECT
    customer_id,
    SUM(amount) AS total_spent
FROM
    orders
WHERE
    order_date BETWEEN '2023-01-01' AND '2023-12-31' -- 先在WHERE过滤年份
GROUP BY
    customer_id
HAVING
    SUM(amount) > 1000; -- 再在HAVING过滤聚合结果
登录后复制

在这个高效的例子中,数据库引擎首先会根据

WHERE
登录后复制
子句过滤掉所有非2023年的订单,这样
GROUP BY
登录后复制
SUM()
登录后复制
只需要处理2023年的数据,大大减少了计算量。

当然,有些时候你别无选择,条件本身就依赖于聚合结果,那就必须使用

HAVING
登录后复制
。这时候,我们能做的就是确保
GROUP BY
登录后复制
的列上建有合适的索引,这有助于加速分组过程。

总的来说,

HAVING
登录后复制
是SQL中一个非常强大且不可或缺的工具,但理解其在查询生命周期中的位置,并结合
WHERE
登录后复制
子句进行合理的划分,是写出高效、可维护SQL查询的关键一步。

以上就是sql怎样使用having结合聚合函数筛选数据 sql聚合筛选与having用法的技巧的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号