首页 游戏 软件 资讯 排行榜 专题
首页
数据库
SQL如何统计分组内的占比情况_SUM聚合函数结合OVER子句

SQL如何统计分组内的占比情况_SUM聚合函数结合OVER子句

热心网友
57
转载
2026-04-30

用 SUM() OVER(PARTITION BY ...) 计算分组内占比最简洁,分子为当前行聚合值,分母为同组总和;需先 GROUP BY 再套窗口函数,避免整数除法截断,注意数据库版本兼容性。

SQL如何统计分组内的占比情况_SUM聚合函数结合OVER子句

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈

怎么用 SUM() OVER() 计算分组内占比

说到计算分组内的占比,SUM() 配合 OVER() 子句堪称是最优雅的方案之一。它最大的好处是什么?简洁。你不再需要写一堆子查询或者自连接,一个窗口函数就能搞定。它的核心逻辑非常清晰:分子是当前行所在分组的聚合值,分母则是整个分组的总和——而这两者的计算范围,都由 OVER(PARTITION BY ...) 这个子句来精确控制。

举个例子就明白了。假设你想统计每个部门里,不同职级的人数占该部门总人数的比例,可以这么写:

SELECT dept, job, COUNT(*) AS cnt,
       COUNT(*) * 1.0 / SUM(COUNT(*)) OVER (PARTITION BY dept) AS ratio
FROM employees
GROUP BY dept, job;

这里有个细节值得注意:COUNT(*) * 1.0。为什么要乘上 1.0?这是为了防止整数除法带来的小数位截断问题。尤其是在 SQL Server 或者 MySQL 8.0 之前的版本里,默认的整数除法会直接丢掉小数部分。虽然 PostgreSQL 和 Oracle 会自动进行类型转换,但显式地乘上 1.0 或者使用 CAST,能让代码的意图更明确,也更具跨数据库的稳健性。

为什么不能只写 SUM() OVER() 不加 PARTITION BY

这是新手常踩的一个坑。如果把 PARTITION BY 子句漏掉了,那 SUM() OVER() 的计算范围就变成了整个结果集。最终你得到的会是“某个职级人数占全公司总人数的比例”,而不是我们想要的“占本部门总人数的比例”。一字之差,结果天差地别。

  • SUM(COUNT(*)) OVER (PARTITION BY dept) → 计算的是每个部门的总人数(这是对的)。
  • SUM(COUNT(*)) OVER () → 计算的是全表的总人数(除非你确实需要全表占比,否则这就是错的)。

另外,还要警惕另一种错误写法:试图在窗口函数里直接嵌套聚合。比如 COUNT(*) OVER (PARTITION BY dept) 这样的语句是会报错的。原因在于,窗口函数的计算是在 GROUP BY 之后进行的,你必须先完成分组聚合,再把聚合结果(比如 COUNT(*))作为窗口函数的输入。正确的顺序永远是:先 GROUP BY,再套上 OVER

不同数据库对 COUNT(*) OVER() 的支持差异

虽然窗口函数如今已是主流,但各数据库的支持情况和细节上仍有差异。像 MySQL 8.0+、PostgreSQL 11+、SQL Server 2005+ 以及 Oracle 20c+ 这些现代版本,都完美支持上面提到的写法。不过,有些特殊情况需要留意:

  • MySQL 5.7 及更早版本完全不支持窗口函数,遇到这种环境,老办法——关联子查询——就得派上用场了。
  • SQLite 3.25+ 虽然支持窗口函数,但 COUNT(*) 在窗口中的使用需要配合 GROUP BY。直接写 COUNT(*) OVER() 可能会遇到语法错误。
  • 在一些旧版本的 Hive 或 Spark SQL 中,引擎对“在窗口函数内嵌套聚合”这种写法的解析可能不太稳定。为了保险起见,更推荐使用 CTE(公用表表达式)将逻辑拆解开来,这样可读性和兼容性都更好:
    WITH grp_cnt AS (
      SELECT dept, job, COUNT(*) AS cnt
      FROM employees GROUP BY dept, job
    )
    SELECT dept, job, cnt,
           cnt * 1.0 / SUM(cnt) OVER (PARTITION BY dept) AS ratio
    FROM grp_cnt;

性能关键点:PARTITION BY 列要有索引吗

一个常见的误解是,为了优化窗口函数,需要特意为 PARTITION BY 的列创建索引。其实不然。窗口函数执行时的性能瓶颈主要在于排序,而查询优化器通常会根据 GROUP BYORDER BY 子句自动决定是否进行排序操作。

那么,什么情况下窗口函数的开销会变大呢?一种比较极端的情形是:PARTITION BY 的列基数非常高(例如是用户ID),导致分成海量的小组,每组只有寥寥几条数据。这时,窗口函数为每个微小分区进行计算的 overhead(开销),有可能会超过传统的子查询方法。当然,这种情况在实践中并不常见。不过,当你面对线上大表查询变慢时,检查执行计划里 WindowAgg 节点的耗时,总是一个不错的诊断思路。

真正对这类查询性能影响巨大的,其实是 GROUP BY 阶段。确保在 deptjob 这两个用于分组的列上建立联合索引(并且索引列的顺序最好与 GROUP BY 子句中间出现的顺序一致),可以极大地避免数据库进行耗时的临时文件排序,这才是提升效率的关键所在。

来源:https://www.php.cn/faq/2328621.html
免责声明: 游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

相关攻略

SQL如何统计分组内的占比情况_SUM聚合函数结合OVER子句
数据库
SQL如何统计分组内的占比情况_SUM聚合函数结合OVER子句

用 SUM() OVER(PARTITION BY ) 计算分组内占比最简洁,分子为当前行聚合值,分母为同组总和;需先 GROUP BY 再套窗口函数,避免整数除法截断,注意数据库版本兼容性。 怎么用 SUM() OVER() 计算分组内占比 说到计算分组内的占比,SUM() 配合 OVER(

热心网友
04.30
如何查找SQL中最值数据_高效使用MAX与MIN聚合函数
数据库
如何查找SQL中最值数据_高效使用MAX与MIN聚合函数

高效使用MAX与MIN聚合函数:如何查找SQL中最值数据 先说一个核心判断:MAX()和MIN()这两个函数,本质是查单列极值的利器,会自动忽略NULL值。但想用好它们,必须记住一个前提:它们必须配合GROUP BY才能与非聚合字段共存,不能直接用来查整行记录,也绝对不能在WHERE子句里直接调用。

热心网友
04.30
SQL如何计算分组内的极差值_MAX与MIN聚合函数应用
数据库
SQL如何计算分组内的极差值_MAX与MIN聚合函数应用

SQL如何计算分组内的极差值:MAX与MIN聚合函数应用 先明确一个核心概念:分组极差,其实就是用组内的最大值减去最小值。这个计算逻辑本身并不复杂,但要想在SQL里写得既准确又高效,有几个关键细节必须得留意。 SQL里用MAX()和MIN()算分组极差,直接相减就行 计算分组极差的公式很直观:分组内

热心网友
04.29
SQL窗口函数与常规聚合函数的性能对比_查询优化指南
数据库
SQL窗口函数与常规聚合函数的性能对比_查询优化指南

窗口函数性能调优:避开那些让你查询变慢的“隐形坑” 先说一个核心判断:窗口函数比 GROUP BY 慢,这几乎是常态。但具体慢多少,很大程度上取决于你定义的分区大小。 窗口函数比 GROUP BY 慢是常态,但慢多少取决于分区大小 窗口函数有个特点:它不减少最终结果的行数。这意味着,OVER子句里定

热心网友
04.29
SQL如何统计分组内数据分布的方差_使用VAR聚合函数
数据库
SQL如何统计分组内数据分布的方差_使用VAR聚合函数

SQL分组方差统计:从函数选择到避坑指南 在数据分析中,衡量一组数据的离散程度,方差是个绕不开的指标。当需要在SQL里按部门、按日期或其他维度分组计算方差时,你可能会发现,事情比想象中要微妙一些。直接调用VAR函数?当然可以,但默认算的是样本方差还是总体方差?不同数据库的语法又是否一致?今天,我们就

热心网友
04.29

最新APP

宝宝过生日
宝宝过生日
应用辅助 04-07
台球世界
台球世界
体育竞技 04-07
解绳子
解绳子
休闲益智 04-07
骑兵冲突
骑兵冲突
棋牌策略 04-07
三国真龙传
三国真龙传
角色扮演 04-07

热门推荐

滚筒洗衣机如何拆洗内桶最彻底?
电脑教程
滚筒洗衣机如何拆洗内桶最彻底?

滚筒洗衣机内桶最彻底的清洁方式 想给滚筒洗衣机内桶来一次真正彻底的清洁?答案只有一个:规范拆解,进行物理级的深度清洗。这可不是简单扔两包清洁剂就能搞定的事,它需要一套严格的技术流程——从断电断水开始,到分步拆卸、精准复装,每一步都马虎不得。核心步骤是:先拆外壳和前封板,再处理门锁和外筒固定结构,接着

热心网友
04.30
opporenocolor11系统可以升级ColorOS几
电脑教程
opporenocolor11系统可以升级ColorOS几

OPPO Reno11系列ColorOS 15 0正式版升级指南与体验解析 好消息来了!OPPO Reno11系列,包括Reno11 5G和Reno11 Pro 5G,现在已经可以升级到ColorOS 15 0正式版了。官方已经为符合条件的用户开放了“新版本尝鲜”通道。不过,升级前有个硬性门槛:你的

热心网友
04.30
老年助听器怎么安装?
电脑教程
老年助听器怎么安装?

老年助听器的安装:一套始于专业、终于适应的科学闭环 很多人以为,给老人戴上助听器,就像戴上一副老花镜那么简单。其实不然。一套真正有效的助听方案,远不止“开机出声”这么简单,它是一套环环相扣的科学流程:从专业的听力验配开始,到个体化的设备适配,再到循序渐进的听觉适应,三者缺一不可。这个过程,始于持证听

热心网友
04.30
以太坊7月收益减半怎么算
web3.0
以太坊7月收益减半怎么算

以太坊7月收益减半怎么算 先说一个核心结论:即将到来的以太坊收益减半,其核心逻辑在于验证者从每个区块中获得的基础共识奖励,将被直接砍掉一半。当然,这并非简单的“腰斩”,因为最终落到个人口袋里的年化收益率,是基础奖励、全网质押总量、Gas费以及MEV(最大可提取价值)收益共同作用的结果。综合来看,个人

热心网友
04.30
CentOS Python数据分析怎么实现
编程语言
CentOS Python数据分析怎么实现

在CentOS系统上实现Python数据分析 想在CentOS服务器上搭建一套高效、稳定的Python数据分析环境?对于许多开发者和数据团队而言,在Linux生产环境中部署数据分析平台是常见需求。本文将提供一份经过验证的、从零开始的详细配置指南,帮助您在CentOS系统上快速构建专业的Python数

热心网友
04.30