Oracle SQL:GROUP BY查询如何返回非分组列及同score值行数统计
Oracle 逐行返回全字段+统计同值score总行数的实现方案
普通GROUP BY score的查询逻辑本身和需求目标存在本质冲突:分组聚合会把所有相同score的行压缩为单行返回,天然无法保留每一行独立的first_name、second_name字段内容,再叠加Oracle对普通分组查询的语法约束,这条路本身就无法实现目标。
最优实现:使用Oracle分析窗口函数
Oracle从8i版本开始原生支持分析窗口函数能力,专门适配「保留原表行粒度,同时按指定范围做聚合统计」的场景,不会对原表行做压缩合并,是该需求下的首选方案。
对应SQL写法:
SELECT first_name, second_name, score, -- 按score划分为独立计算分区,统计分区内总行数即当前score的全局出现次数 COUNT(*) OVER (PARTITION BY score) AS same_score_total FROM tab;
该写法的运行逻辑:
OVER (PARTITION BY score)会把全表数据按照score的值拆成多个逻辑计算分区,过程中不会合并、删除分区内的原有数据行- 窗口内的
COUNT(*)仅在当前行所属的score分区范围内做计数,不会跨分区统计 - 最终返回的结果行数和原表完全一致,逐行保留原表全部字段的同时,在每一行追加当前score对应的全局重复出现次数
低版本环境备选:聚合结果自关联
如果碰到不支持窗口函数的极老旧Oracle版本,可以通过原表与预聚合结果内连接的方式兜底实现:
SELECT t.first_name, t.second_name, t.score, agg.same_score_total FROM tab t -- 提前计算每个score对应的全局出现次数 INNER JOIN ( SELECT score, COUNT(*) AS same_score_total FROM tab GROUP BY score ) agg ON t.score = agg.score;
该方案的缺点是需要对同一张表做两次全量扫描,数据量较大时性能远低于窗口函数方案,不建议在常规生产环境使用。
内容的提问来源于stack exchange,提问作者Sa1m0n
相关产品推荐
相关产品推荐

