查询Oracle平均重做日志使用量(GB)时遭遇ORA-00937错误求助
解决ORA-00937: not a single-group group function错误
这个错误的根源很明确:当你在SQL中使用聚合函数(比如AVG())时,所有未被聚合函数包裹的列必须全部出现在GROUP BY子句里。你的查询里同时选择了Start_Date、Start_Time、Num_Logs、Dbname这些非聚合列和AVG(),但没有把它们加入GROUP BY,Oracle无法确定这些列如何与聚合结果对应,所以抛出了这个错误。
结合你的需求(按日/小时统计重做日志使用量并转为GB),我分两种场景给你修正方案:
场景1:按日和小时统计每个时段的日志用量(GB)
如果你的真实需求是展示每个小时段的实际日志使用量(而非平均值),那AVG()其实是多余的——子查询已经按日/小时分组统计了该时段的日志数量,直接计算GB值即可:
SELECT Log_Hist.Start_Date, Log_Hist.Start_Time, Log_Hist.Num_Logs, ROUND(Log_Hist.Num_Logs * (Vl.Bytes / (1024 * 1024 * 1024)), 2) AS Gbytes, Vdb.NAME AS Dbname FROM ( SELECT To_Char(Vlh.First_Time, 'YYYY-MM-DD') AS Start_Date, To_Char(Vlh.First_Time, 'HH24') || ':00' AS Start_Time, COUNT(Vlh.Thread#) AS Num_Logs FROM V$log_History Vlh GROUP BY To_Char(Vlh.First_Time, 'YYYY-MM-DD'), To_Char(Vlh.First_Time, 'HH24') || ':00' ) Log_Hist CROSS JOIN V$log Vl CROSS JOIN V$database Vdb WHERE Vl.Group# = 1 ORDER BY Log_Hist.Start_Date, Log_Hist.Start_Time;
说明:
- 用显式
CROSS JOIN替代隐式连接,让逻辑更清晰(因为V$database只有一条记录,V$log取Group#=1的单条记录) - 去掉多余的
AVG(),直接计算每个时段的GB用量 - 假设所有日志组大小一致,所以用
Vl.Group#=1取单组的字节数,如果日志组大小不同,可以改用AVG(Vl.Bytes)获取平均日志大小
场景2:计算平均日志用量(比如按日统计平均每小时用量)
如果你确实需要计算平均值,比如按天统计全天的平均每小时日志用量,那需要调整GROUP BY子句,只保留需要分组的列:
SELECT Log_Hist.Start_Date, AVG(ROUND(Log_Hist.Num_Logs * (Vl.Bytes / (1024 * 1024 * 1024)), 2)) AS AVG_Daily_Gbytes, Vdb.NAME AS Dbname FROM ( SELECT To_Char(Vlh.First_Time, 'YYYY-MM-DD') AS Start_Date, To_Char(Vlh.First_Time, 'HH24') || ':00' AS Start_Time, COUNT(Vlh.Thread#) AS Num_Logs FROM V$log_History Vlh GROUP BY To_Char(Vlh.First_Time, 'YYYY-MM-DD'), To_Char(Vlh.First_Time, 'HH24') || ':00' ) Log_Hist CROSS JOIN V$log Vl CROSS JOIN V$database Vdb WHERE Vl.Group# = 1 GROUP BY Log_Hist.Start_Date, Vdb.NAME ORDER BY Log_Hist.Start_Date;
说明:
- 仅保留
Start_Date和Dbname在SELECT中,并将它们加入GROUP BY AVG()计算的是当天所有小时段日志用量的平均值
内容的提问来源于stack exchange,提问作者Jonny
相关产品推荐
相关产品推荐

