ORA-00937非单组分组函数错误:如何从顶层解决该问题?
解决Oracle ORA-00937错误:非单组分组函数问题
错误原因
ORA-00937错误的核心是违反了Oracle分组查询规则:你的最外层SELECT同时包含year、Net_TWRR_PERIOD这类非聚合字段,以及SUM()这类聚合函数,但未指定对应的GROUP BY子句。Oracle要求,只要查询中使用了聚合函数,所有未被聚合的列必须明确出现在GROUP BY子句中,否则就会触发该错误。
解决方法
根据业务需求,有两种修正方向:
方向1:按year分组计算外层聚合结果
如果需要基于内层已计算的年度数据,继续按year做聚合,只需在最外层查询末尾添加GROUP BY year,同时调整SELECT列表(不需要保留Net_TWRR_PERIOD,因为它是内层的年度结果,外层聚合时需用其做计算而非直接输出)。
修正后的完整SQL:
SELECT year, ROUND( ( CASE WHEN MOD(SUM(CASE WHEN Net_TWRR_PERIOD < 0 THEN 1 ELSE 0 END), 2) = 1 THEN -1 ELSE 1 END * EXP(SUM(LN(ABS(Net_TWRR_PERIOD)))) - 1 ) * 100, 2 ) AS final_calculated_value FROM ( SELECT year, ROUND( ( CASE WHEN MOD(SUM(CASE WHEN Net_TWRR < 0 THEN 1 ELSE 0 END), 2) = 1 THEN -1 ELSE 1 END * EXP(SUM(LN(ABS(Net_TWRR)))) - 1 ) * 100, 2 ) AS Net_TWRR_PERIOD FROM ( SELECT (net_rate_of_return / 100 + 1) AS Net_TWRR, year FROM eom WHERE id = '2' AND start_date < '09-September-2022' ) GROUP BY year ) GROUP BY year ORDER BY year;
方向2:对所有行做整体聚合
如果不需要按year分组,而是要对内层所有年度结果做整体计算,那么需要移除year和Net_TWRR_PERIOD这两个非聚合字段,仅保留聚合计算的结果:
修正后的SQL示例:
SELECT ROUND( ( CASE WHEN MOD(SUM(CASE WHEN Net_TWRR_PERIOD < 0 THEN 1 ELSE 0 END), 2) = 1 THEN -1 ELSE 1 END * EXP(SUM(LN(ABS(Net_TWRR_PERIOD)))) - 1 ) * 100, 2 ) AS overall_calculated_value FROM ( SELECT year, ROUND( ( CASE WHEN MOD(SUM(CASE WHEN Net_TWRR < 0 THEN 1 ELSE 0 END), 2) = 1 THEN -1 ELSE 1 END * EXP(SUM(LN(ABS(Net_TWRR)))) - 1 ) * 100, 2 ) AS Net_TWRR_PERIOD FROM ( SELECT (net_rate_of_return / 100 + 1) AS Net_TWRR, year FROM eom WHERE id = '2' AND start_date < '09-September-2022' ) GROUP BY year );
核心规则总结
- 当查询使用聚合函数(SUM、COUNT、AVG等)时,SELECT列表中的所有非聚合字段必须全部包含在GROUP BY子句中;
- 若不需要分组,SELECT列表中只能包含聚合函数的计算结果,不能出现单独的列。
内容的提问来源于stack exchange,提问作者user19427142
相关产品推荐
相关产品推荐

