如何使用HAVING子句结合SUM()函数筛选占比超3/4的用户数据
解决筛选占比超3/4用户的SQL问题
我来帮你搞定这个HAVING子句的困惑!其实你遇到的问题核心是需要用整个表的总小时数来做占比计算,而不是分组后的总和,所以直接用HAVING可能不是最直接的方式,下面给你两种简单可行的方案:
方案1:子查询获取全局总小时数
这种方法最直观,先通过子查询算出整个表的总小时数,再用WHERE子句筛选符合占比条件的记录:
SELECT Username, SummedHourCount FROM your_table WHERE SummedHourCount / (SELECT SUM(SummedHourCount) FROM your_table) > 0.75;
说明:
- 子查询
(SELECT SUM(SummedHourCount) FROM your_table)会计算出所有用户的总小时数(你的例子里是13+1+2+1=17) - 每条记录的
SummedHourCount除以这个全局总数,判断是否大于3/4(也就是0.75) - 注意:如果你的数据库默认是整数除法(比如MySQL),建议把计算改成
SummedHourCount * 1.0 / (SELECT SUM(SummedHourCount) FROM your_table) > 0.75,避免整数相除导致结果被截断为整数
方案2:用窗口函数计算全局总和
如果你想用更高效的方式(尤其是大表场景),可以用窗口函数SUM() OVER()直接给每行加上全局总小时数,再筛选:
SELECT Username, SummedHourCount FROM ( SELECT Username, SummedHourCount, SUM(SummedHourCount) OVER() AS TotalHours FROM your_table ) AS sub_query WHERE SummedHourCount * 1.0 / TotalHours > 0.75;
说明:
SUM(SummedHourCount) OVER()会为每一行生成整个表的总小时数,不需要额外的子查询扫描- 外层查询只需要判断每行的小时数占总小时数的比例即可
为什么不用HAVING?
HAVING子句是配合GROUP BY使用的,用来筛选分组后的聚合结果。比如如果你要按用户分组(其实你的表已经是按用户分组后的结果了),那用HAVING的话需要先把全局总和作为一个聚合值带进来,反而不如上面两种方法简洁。比如这种写法也能实现,但没必要:
SELECT Username, SummedHourCount FROM your_table CROSS JOIN (SELECT SUM(SummedHourCount) AS Total FROM your_table) AS total_hours GROUP BY Username, SummedHourCount, Total HAVING SummedHourCount / Total > 0.75;
用你给的测试数据,上面三种方法都会返回:
Username | SummedHourCount
randy.jackson | 13
内容的提问来源于stack exchange,提问作者TheEggSample
相关产品推荐
相关产品推荐

