百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

SQL 中 HAVING 的奇妙世界(sql+中+having+的奇妙世界有哪些)

wptr33 2025-04-06 22:14 34 浏览

HAVING 在 SQL 里可重要啦,它常常跟 GROUP BY 子句一块用,能给聚合函数的结果做过滤。

在 SQL 查询里,GROUP BY 子句能把数据按特定的列分好组。HAVING 子句就在分组完了以后起作用,它能根据聚合函数的结果,把满足特定条件的组挑出来。比如说,在一个卖东西的数据表里头,咱们能靠 GROUP BY 按销售员来分组,然后用 HAVING 子句把总销售额超过一定数的销售员选出来。

HAVING 子句的作用主要在这么几个地方:头一个,它能对聚合函数算出来的结果输出做限制。好比说,咱们可能就只想看销售总额超过 1500 美元的商店信息,这时候就得用 HAVING 子句。语法格式一般是这样:SELECT "column_name1", SUM ("column_name2") FROM "table_name" GROUP BY "column_name1" HAVING (arithematic function condition)。

HAVING 子句被限制在 SELECT 语句里已经定义好的列和聚合表达式上头。通常,咱们得在 HAVING 子句里再重复一遍聚合函数表达式来引用聚合的值,就跟在 SELECT 语句里做的一样。比如说:SELECT A COUNT (B) FROM TABLE GROUP BY A HAVING COUNT (B)>2。

反正,HAVING 在 SQL 里给咱们提供了一个厉害的工具,能对分组以后的聚合结果做精准的筛选,这样就能满足各种麻烦的查询需要啦。

二、HAVING 与 WHERE 的区别

(一)作用的阶段不一样

WHERE 子句是在数据分组前给原始数据做过滤,就是说它在查询刚开始的时候起作用,用来限制进入分组和聚合操作的数据。比如说,在一个卖东西的数据表里,如果咱们想找销售额大于 1000 的记录,在分组前就能用 WHERE 子句来筛选,像 SELECT product_id, SUM(quantity) AS total_quantity FROM sales WHERE sales_amount > 1000 GROUP BY product_id;,这个查询就只给销售额大于 1000 的记录做分组求和。

可 HAVING 子句是在数据分组以后给分组结果做过滤,就是说它在 GROUP BY 子句后面起作用,用来限制最终结果里的分组。比如 SELECT product_id, SUM(quantity) AS total_quantity FROM sales GROUP BY product_id HAVING SUM(quantity)>100;,这个查询会对所有产品按 product_id 分组求和,然后只给出总数量大于 100 的分组。

(二)使用的限制不一样

WHERE 子句能对单个的记录做条件判断,比如说对列值的具体数字做过滤,但是不能对聚合函数做判断。比如说,咱们不能写 SELECT product_id,SUM(quantity) AS total_quantity FROM sales WHERE SUM(quantity)>100 GROUP BY product_id;,这样的查询会报错,因为 WHERE 不能用聚合函数。

HAVING 子句通常是跟聚合函数(像 SUM (), AVG (), COUNT () 这些)一块用,对分组后的结果做条件判断。比如 SELECT customer_id, SUM(sales_amount) AS total_sales FROM sales GROUP BY customer_id HAVING SUM(sales_amount)>10000;,这个查询会把所有销售总额超过 10000 的客户返回。

反正,WHERE 和 HAVING 在 SQL 查询里都挺重要的,不过因为它们作用的阶段和使用的限制不一样,咱们得按照具体的查询需要来选合适的子句。

三、HAVING 的常见用法

(一)跟聚合函数一块用

HAVING 经常跟聚合函数一块用,发挥出很强的筛选作用。比如说,在一个卖东西的数据表里,咱们想查平均销售额超过 5000 的客户信息。能这么写 SQL 语句:SELECT customer_id, AVG(sales_amount) AS avg_sales FROM sales_data GROUP BY customer_id HAVING AVG(sales_amount)>5000;。在这,靠 AVG 聚合函数算出每个客户的平均销售额,然后用 HAVING 子句把平均销售额大于 5000 的客户挑出来。根据一些实际例子的数据统计,要是销售数据表有 1000 个客户的记录,当中满足平均销售额超过 5000 的客户可能就几十位,HAVING 子句就能准确地找出这些特定的客户信息。

(二)跟 GROUP BY 子句一块用

HAVING 跟 GROUP BY 子句一块用的时候,能对分组后的结果做有针对性的筛选。好比在一个学生成绩表里头,按照班级来分组,然后找出平均分超过 80 分的班级信息。SQL 语句是这样:SELECT class_id, AVG(score) AS avg_score FROM student_scores GROUP BY class_id HAVING AVG(score)>80;。靠 GROUP BY 子句把学生成绩按班级分好组,再用 HAVING 子句把平均分高于 80 分的班级选出来。在实际的学校成绩管理系统里,这样的查询能帮老师很快搞清楚哪些班级整体成绩比较好,方便做有针对性的教学调整。

(三)跟其他子句联合用

HAVING 能跟 WHERE 子句这些联合起来用,满足更复杂的查询需要。比如说在一个订单表里头,先靠 WHERE 子句把特定时间段里的订单记录选出来,然后再用 GROUP BY 子句按客户分组,最后用 HAVING 子句把总订单金额超过一定数的客户信息选出来。SQL 语句像这样:SELECT customer_id, SUM(order_amount) AS total_amount FROM orders WHERE order_date BETWEEN '2023-01-01' AND '2023-12-31' GROUP BY customer_id HAVING SUM(order_amount)>10000;。在这,WHERE 子句先把 2023 年的订单记录选出来,然后 GROUP BY 子句按客户分组,最后 HAVING 子句把总订单金额超过 10000 的客户选出来。这种联合使用的办法在实际的业务数据分析里特别常见,能帮咱们从复杂的数据里找出有价值的信息。

四、HAVING 的性能优化

(一)少点数据量

在用 HAVING 子句之前,尽量靠 WHERE 子句把没必要的数据给过滤掉,让处理的数据量变少点。比如说,在一个很大的销售数据表里头,咱们能先使 WHERE sales_date > '2023-01-01' 把特定时间段里的销售记录给筛出来,这么着在做分组和用 HAVING 子句筛选的时候,处理的数据量就能少好多。按照实际的数据统计,要是销售数据表有 100 万条记录,通过合理的 WHERE 子句过滤一下,可能就剩下 10 万条记录用来后面的分组和 HAVING 筛选,这样就能明显把查询性能提高。

(二)用上索引

保证在用来分组的列上弄好索引,把查询性能提上去。索引能让数据检索的速度变快,特别是处理大量数据的时候。好比在一个有客户信息和订单信息的数据库里,如果老是按客户 ID 分组还用上 HAVING 子句筛选,那在客户 ID 这列上弄个索引就能大大提高查询的效率。假设没索引的时候,查询得花 10 秒钟,弄上索引可能 2 秒钟就能把一样的查询做完。

(三)别弄复杂计算

在 HAVING 子句里别用复杂的计算和函数,这些计算可能会对性能有不好的影响。比如说,别在 HAVING 子句里用好几层嵌套的函数调用或者复杂的算术运算。要是非得做复杂计算,可以想想把计算结果存到临时表里,然后在 HAVING 子句里用临时表的列来筛选。这样能把 HAVING 子句执行时候的计算量变少,把查询性能提高。

(四)分析查询的计划

用数据库给的查询计划分析工具,瞅瞅查询的执行计划,找找可能的性能瓶颈。通过分析查询计划,咱们能知道数据库是咋执行查询的,包括用了啥索引、做了啥排序操作这些。比如说,在一个复杂的查询里,咱们可能发现数据库在执行 HAVING 子句的时候做了好多全表扫描,这可能就是性能瓶颈的地方。通过调整查询语句或者优化数据库的结构,能把查询性能变好。假设分析完查询计划,咱们发现能通过加合适的索引或者调整 WHERE 子句的条件来少做点全表扫描,这样就能把查询速度提上去。

五、HAVING 的实际应用案例

(一)找高销售额的客户

在销售数据的分析里,咱们经常得把高销售额的客户找出来。比如说在一个电商平台的销售数据库里,咱们能使下面这个 SQL 语句来找销售总额超过 100000 的客户:SELECT customer_id, SUM(sales_amount) AS total_sales FROM sales_table GROUP BY customer_id HAVING SUM(sales_amount)>100000;。假设这个电商平台有 10000 个客户,靠这个查询,咱们可能能找出几十或者几百个高销售额的客户。这些客户对平台来说是重要的客户群,能针对他们搞个性化的营销活动,把客户的满意度和忠诚度提上去。

(二)找高库存的产品

对企业的库存管理来说,清楚哪些产品库存太高或者太低特别重要。靠 HAVING 子句能很快把库存数量超过特定值的产品筛出来。好比在一个仓库管理系统里,使下面这个 SQL 语句:SELECT product_id, SUM(quantity) AS total_quantity FROM inventory_table GROUP BY product_id HAVING SUM(quantity)>500;。要是仓库里有 1000 种产品,这个查询能帮咱们把那些库存数量超过 500 的产品找出来。对这些高库存产品,企业能考虑搞促销活动或者调整生产计划,把库存成本降下来。

(三)找高绩效的员工

在人力资源管理里,评估员工的绩效是个重要的活儿。用 HAVING 子句能把绩效评分均值超过特定值的员工找出来。比如说在一个员工绩效评估系统里,使下面这个 SQL 语句:SELECT employee_id, AVG(performance_score) AS avg_score FROM performance_table GROUP BY employee_id HAVING AVG(performance_score)>4.5;。假设公司有 1000 名员工,靠这个查询能把那些绩效表现好的员工找出来。对这些高绩效员工,能给奖励或者晋升的机会,激励别的员工把绩效提上去。

(四)找高流量的网页

在网站分析里,清楚哪些网页的访问量高对优化网站的内容和布局特别重要。用 HAVING 子句能把访问次数超过特定值的网页找出来。好比在一个网站流量分析系统里,使下面这个 SQL 语句:SELECT page_url, COUNT(visitor_id) AS total_visits FROM web_traffic_table GROUP BY page_url HAVING COUNT(visitor_id)>1000;。要是网站有 10000 个页面,这个查询能帮咱们把那些访问量高的页面找出来。对这些高流量网页,能进一步分析用户的行为,优化页面的内容和布局,把用户体验提上去。

六、HAVING 的注意事项

(一)跟 GROUP BY 子句的关系

HAVING 子句一定得跟 GROUP BY 子句一块用,不能自己单着。这是因为 HAVING 是用来给分组后的结果做过滤的,而分组这个操作是 GROUP BY 子句干的。比如说,要是咱们只使 HAVING 子句,没有 GROUP BY 子句,数据库就会报错,因为没有分组的结果能让 HAVING 子句来筛选。

(二)支持的东西

HAVING 子句能使聚合函数,像 SUM、COUNT、AVG 这些。这就让咱们能按照分组后的聚合结果来做过滤。比如说,咱们能使 SELECT product_id, SUM(quantity) AS total_quantity FROM inventory_table GROUP BY product_id HAVING SUM(quantity)>500; 来找库存总量超过 500 的产品。这儿的 SUM(quantity) 就是聚合函数,HAVING 子句就照着这个聚合结果来做过滤。 HAVING 子句是用来过滤组的,不是单个的记录。它是在数据分组完了以后才用的,跟 WHERE 子句不一样,WHERE 子句是在数据分组前过滤行的。

(三)对性能的影响

因为 HAVING 子句是在数据分组以后才用的,所以它可能会对查询的性能有影响。特别是处理大量数据的时候,HAVING 子句可能会带来额外的计算和数据处理,让查询的速度变慢。

为了把 HAVING 子句的性能优化一下,咱们能做点事儿。比如说,在用 HAVING 子句之前,尽量靠 WHERE 子句把没必要的数据给过滤掉,让处理的数据量变少。同时,保证在用来分组的列上弄好索引,把查询性能提上去。别在 HAVING 子句里用复杂的计算和函数,也能少点性能上的开销。

(四)跟 WHERE 子句的差别

HAVING 子句跟 WHERE 子句的用处和功能不一样。WHERE 子句是在数据分组前过滤行的,不能用聚合函数。

可 HAVING 子句是在数据分组后过滤组的,能使聚合函数。 在选是用 WHERE 子句还是 HAVING 子句的时候,得按照具体的情况来判断。要是对单个记录做条件判断,或者在分组前过滤,就该用 WHERE 子句。要是对分组后的结果做条件判断,或者得用聚合函数来过滤,就该用 HAVING 子句。

七、HAVING 的高级用法

(一)用多个条件

SQL 的 HAVING 子句能把多个条件合起来,查满足特定要求的分组结果。比如说,下面这个 SQL 语句能找销售额大于 1000 并且订单数大于 10 的销售人员:SELECT salesman_id, SUM(sales_amount) AS total_sales, COUNT(order_id) AS total_orders FROM sales_table GROUP BY salesman_id HAVING SUM(sales_amount)>1000 AND COUNT(order_id)>10;。在这用了 SUM 和 COUNT 两个聚合函数,靠 AND 把两个条件连起来了,给分组后的销售人员做筛选。在实际用的时候,多个条件组合起来能更准地满足复杂的查询需要。假设在一个有 1000 条销售记录的数据库里,可能就只有很少的销售人员能同时满足销售额大于 1000 而且订单数大于 10 这个条件,HAVING 子句的多个条件能帮咱们很快找到这些特定的销售人员。

(二)用子查询

子查询在 HAVING 子句里能起大作用,帮咱们筛出特定的分组结果。比如说,咱们想找平均销售额比所有销售人员平均销售额高的销售人员,就能用子查询来实现。SQL 语句像这样:SELECT salesman_id, AVG(sales_amount) AS avg_sales FROM sales_table GROUP BY salesman_id HAVING AVG(sales_amount)>(SELECT AVG(sales_amount) FROM sales_table);。这儿的子查询(SELECT AVG(sales_amount) FROM sales_table)先算出所有销售人员的平均销售额,然后主查询里的 HAVING 子句把每个销售人员的平均销售额跟这个值比一比,把比平均值高的销售人员筛出来。在实际的数据分析里,子查询能根据不同的需要灵活地定筛选条件,让 HAVING 子句的功能更强。假设在一个有 50 个销售人员的数据库里,靠这个查询能找出那些销售业绩特别好的销售人员,给企业的销售管理提供有价值的信息。

八、HAVING 的使用场景

(一)显示特定地区的信息

在分析数据的时候,经常得只显示面积超过特定值的地区的总人口数和总面积。比如说,SELECT region, SUM(population), SUM(area) FROM test GROUP BY region HAVING SUM(area)>1000000;,这个 SQL 语句从叫 test 的表里,按照地区分组,然后把总面积超过 1000000 的地区挑出来,显示这些地区的名字、总人口数和总面积。假设在一个地理数据库里有 50 个不一样的地区,靠这个查询咱们能很快找出那些面积大的地区,好做进一步的分析和决定。

(二)筛选联合查询的结果

在 union 联合查询里,HAVING 能用来挑出不重复的时间段。比如说,SELECT date FROM (SELECT DISTINCT(date) FROM abc.test1 UNION ALL SELECT DISTINCT(date) FROM abc.test2 ) a GROUP BY date HAVING count(*)<=1;,这个查询从两个不同的表 abc.test1 abc.test2 date 1000 select snocount from sc where grade>=90 group by sno;,这个查询从学生成绩表 sc 里,找出成绩大于等于 90 分的课程数量,

按学生编号分组。假设学生成绩表有 1000 个学生的成绩记录,靠这个查询能知道每个学生的优秀课程数量。 能筛出至少两门成绩在特定值以上的学生。比如 select sno,count(*) from sc where grade>=90 group by sno having count(*)>2;,这个查询在上面那个的基础上,再把成绩大于等于 90 分的课程数量至少两门的学生筛出来。

能找出满足特定条件有资格的学生。比如说,select sno,avg(grade) from sc where SNO IN(SELECT SNO FROM SC WHERE GRADE>=95 AND PNO='YW') group by sno having avg(grade)>90;,这个查询先从学生成绩表中找出语文课成绩大于等于 95 分的学生编号,然后再按这些学生编号算平均成绩,把平均成绩大于 90 分的学生筛出来。

(四)比较查询

能查比特定学生平均成绩高的学生学号和平均分数。比如说,select sno,avg(grade) from sc group by sno having avg(grade)>(select avg(grade) from sc where sno=3);,这个查询从学生成绩表中,按学生编号分组算平均成绩,然后把平均成绩比学号为 3 的学生平均成绩高的学生学号和平均分数筛出来。假设学生成绩表有 500 个学生的成绩记录,靠这个查询能找出那些成绩相对好的学生,给教学评估做参考。

(五)获取维度的 topN

用 HAVING in 拿前 N 条维度项。比如说,select area,category,sales sum_index_sales_0 from(select area,category,sales from localdoc_topN t) a group by area,category,sales having area in(select areafrom(select area,sum(sales) sum_index_sales_0 from localdoc_topN group by area order by sum_index_sales_0 desc limit 2) b) limit 5000;,这个查询从叫 localdoc_topN 的表里,先按地区、类别和销售额分组,然后把地区在特定范围里的前 5000 条记录筛出来。假设这个表有 10000 条记录,靠这个查询能很快拿到特定维度的前几条数据。

用 row_number 函数拿每个维度的前 N 条数据。比如说,select area,category,index_sales_0 from(select area,category,sum(sales) index_sales_0,row_number() over(partition by area order by sum(sales) desc) rank_num from(select area,category,sales from localdoc_topN) t group by area,category) a where a.rank_num<=2 limit 5000;,这个查询通过窗口函数 row_number()给每个地区的销售额排名,然后把排名在前两位的记录筛出来,限制返回结果是 5000 条。在实际数据分析里,能按照不同的需要灵活调整排名和限制条件,拿到想要的维度数据。

相关推荐

oracle数据导入导出_oracle数据导入导出工具

关于oracle的数据导入导出,这个功能的使用场景,一般是换服务环境,把原先的oracle数据导入到另外一台oracle数据库,或者导出备份使用。只不过oracle的导入导出命令不好记忆,稍稍有点复杂...

继续学习Python中的while true/break语句

上次讲到if语句的用法,大家在微信公众号问了小编很多问题,那么小编在这几种解决一下,1.else和elif是子模块,不能单独使用2.一个if语句中可以包括很多个elif语句,但结尾只能有一个else解...

python continue和break的区别_python中break语句和continue语句的区别

python中循环语句经常会使用continue和break,那么这2者的区别是?continue是跳出本次循环,进行下一次循环;break是跳出整个循环;例如:...

简单学Python——关键字6——break和continue

Python退出循环,有break语句和continue语句两种实现方式。break语句和continue语句的区别:break语句作用是终止循环。continue语句作用是跳出本轮循环,继续下一次循...

2-1,0基础学Python之 break退出循环、 continue继续循环 多重循

用for循环或者while循环时,如果要在循环体内直接退出循环,可以使用break语句。比如计算1至100的整数和,我们用while来实现:sum=0x=1whileTrue...

Python 中 break 和 continue 傻傻分不清

大家好啊,我是大田。今天分享一下break和continue在代码中的执行效果是什么,进一步区分出二者的区别。一、continue例1:当小明3岁时不打印年龄,其余年龄正常循环打印。可以看...

python中的流程控制语句:continue、break 和 return使用方法

Python中,continue、break和return是控制流程的关键语句,用于在循环或函数中提前退出或跳过某些操作。它们的用途和区别如下:1.continue(跳过当前循环的剩余部分,进...

L017:continue和break - 教程文案

continue和break在Python中,continue和break是用于控制循环(如for和while)执行流程的关键字,它们的作用如下:1.continue:跳过当前迭代,...

作为前端开发者,你都经历过怎样的面试?

已经裸辞1个月了,最近开始投简历找工作,遇到各种各样的面试,今天分享一下。其实在职的时候也做过面试官,面试官时,感觉自己问的问题很难区分候选人的能力,最好的办法就是看看候选人的github上的代码仓库...

面试被问 const 是否不可变?这样回答才显功底

作为前端开发者,我在学习ES6特性时,总被const的"善变"搞得一头雾水——为什么用const声明的数组还能push元素?为什么基本类型赋值就会报错?直到翻遍MDN文档、对着内存图反...

2023金九银十必看前端面试题!2w字精品!

导文2023金九银十必看前端面试题!金九银十黄金期来了想要跳槽的小伙伴快来看啊CSS1.请解释CSS的盒模型是什么,并描述其组成部分。答案:CSS的盒模型是用于布局和定位元素的概念。它由内容区域...

前端面试总结_前端面试题整理

记得当时大二的时候,看到实验室的学长学姐忙于各种春招,有些收获了大厂offer,有些还在苦苦面试,其实那时候的心里还蛮忐忑的,不知道自己大三的时候会是什么样的一个水平,所以从19年的寒假放完,大二下学...

由浅入深,66条JavaScript面试知识点(七)

作者:JakeZhang转发链接:https://juejin.im/post/5ef8377f6fb9a07e693a6061目录由浅入深,66条JavaScript面试知识点(一)由浅入深,66...

2024前端面试真题之—VUE篇_前端面试题vue2020及答案

添加图片注释,不超过140字(可选)1.vue的生命周期有哪些及每个生命周期做了什么?beforeCreate是newVue()之后触发的第一个钩子,在当前阶段data、methods、com...

今年最常见的前端面试题,你会做几道?

在面试或招聘前端开发人员时,期望、现实和需求之间总是存在着巨大差距。面试其实是一个交流想法的地方,挑战人们的思考方式,并客观地分析给定的问题。可以通过面试了解人们如何做出决策,了解一个人对技术和解决问...