[Err] ORA-00979: not a GROUP BY expression

本文详细介绍了Oracle SQL中GROUP BY子句的正确用法,包括如何避免notaGROUPBYexpression异常,如何正确使用SELECT列表中的字段,以及如何结合HAVING子句筛选分组结果。此外还介绍了ORDER BY子句在GROUP BY中的应用。

Oracle中group by用法

not a GROUP BY expression异常产生是因为group by用法的问题。
在使用group by 时,有一个规则需要遵守,即出现在select列表中的字段,如果没有在组函数中,那么必须出现在group by 子句中。(select中的字段不可以单独出现,必须出现在group语句中或者在组函数中。)
否则就会出现错误。

在select 语句中可以使用group by 子句将行划分成较小的组,一旦使用分组后select操作的对象变为各个分组后的数据,使用聚组函数返回的是每一个组的汇总信息。

使用having子句 限制返回的结果集。group by 子句可以将查询结果分组,并返回行的汇总信息Oracle 按照group by 子句中指定的表达式的值分组查询结果。

在带有group by 子句的查询语句中,在select 列表中指定的列要么是group by 子句中指定的列,要么包含聚组函数 select max(sal),job emp group by job; (注意max(sal),job的job并非一定要出现,但有意义) 查询语句的select 和group by ,having 子句是聚组函数唯一出现的地方,在where 子句中不能使用聚组函数。 select deptno,sum(sal) from emp where sal>1200 group by deptno having sum(sal)>8500 order by deptno; 当在gropu by 子句中使用having 子句时,查询结果中只返回满足having条件的组。在一个sql语句中可以有where子句和having子句。having 与where 子句类似,均用于设置限定条件 where 子句的作用是在对查询结果进行分组前,将不符合where条件的行去掉,即在分组之前过滤数据,条件中不能包含聚合函数,使用where条件显示特定的行。
having 子句的作用是筛选满足条件的组,即在分组之后过滤数据,条件中经常包含聚合函数,使用having 条件显示特定的组,也可以使用多个分组标准进行分组。

使用order by排序时order by子句置于group by 之后 并且 order by 子句的排序标准不能出现在select查询之外的列。

查询每个部门的每种职位的雇员数
select deptno,job,count(*) from emp group by deptno,job

/******************************************************

记住这就行了:

在使用group by 时,有一个规则需要遵守,即出现在select列表中的字段,如果没有在组函数中,那么必须出现在group by 子句中。(select中的字段不可以单独出现,必须出现在group语句中或者在组函数中。)

您遇到的错误信息如下: ``` Error: SQLCODE: -937, SQLERRM: ORA-00937: not a single-group group function ORA-02063: preceding line from SJMM ORA-06512: at "SJWOUSER_T.PRC_WT_AA_TTF", line 189 ``` 这是一个 **Oracle 数据库 SQL 错误**,虽然不是直接的 Java 错误,但在使用 Java(如通过 JDBC)执行 SQL 查询时,如果 SQL 语句不合法,就会抛出此类异常。 --- ### ✅ 回答问题 #### ❌ 错误原因:`ORA-00937: not a single-group group function` 这个错误的意思是:**您在查询中混合使用了聚合函数(如 `SUM`, `COUNT`, `AVG`, `MAX`, `MIN` 等)和非聚合字段,但没有正确使用 GROUP BY 子句。** 在 SQL 中: - 如果查询中包含聚合函数,并且还选择了非聚合字段,则必须将这些非聚合字段放在 `GROUP BY` 子句中。 - 否则 Oracle 不知道如何“分组”数据来计算聚合值。 --- ### 🧠 示例说明 假设您的 SQL 语句类似这样(常见错误): ```sql SELECT deptno, empname, SUM(salary) FROM employees WHERE status = 'ACTIVE' ; ``` ❌ 这会报 ORA-00937 错误,因为: - `deptno` 和 `empname` 是普通列(非聚合) - `SUM(salary)` 是聚合函数 - 没有 `GROUP BY` ✅ 正确写法应该是: ```sql SELECT deptno, empname, SUM(salary) FROM employees WHERE status = 'ACTIVE' GROUP BY deptno, empname; ``` 或者,如果您想按部门汇总工资,只查部门级数据: ```sql SELECT deptno, SUM(salary) FROM employees WHERE status = 'ACTIVE' GROUP BY deptno; ``` --- ### ⚠️ 特别注意分布式查询中的问题(ORA-02063) 您看到的: ``` ORA-02063: preceding line from SJMM ``` 表示这个 SQL 查询涉及 **数据库链接(DB Link)** 到远程数据库 `SJMM`。这意味着: - 查询可能跨两个数据库执行。 - 聚合操作在分布式环境下更容易出错,尤其是 Oracle 对通过 DB Link 的查询限制更多。 👉 解决方案建议: 1. 尽量避免在远程表上做复杂的聚合而不加 `GROUP BY`。 2. 可以先从远程数据库拉取必要数据到本地临时表,再进行聚合处理。 3. 或者改写为在远程数据库上完成聚合后返回结果。 例如,不要这样写: ```sql SELECT e.deptno, SUM(e.salary) FROM emp@SJMM e, dept d WHERE e.deptno = d.deptno -- 没有 GROUP BY ; ``` 而应改为: ```sql SELECT e.deptno, SUM(e.salary) FROM emp@SJMM e, dept d WHERE e.deptno = d.deptno GROUP BY e.deptno; ``` --- ### 🔍 在 Java 中如何避免? 当使用 JDBC 执行 SQL 时,请确保传入的 SQL 字符串是语法正确的,尤其是在拼接字符串时容易遗漏 `GROUP BY`。 示例(Java + JDBC): ```java String sql = """ SELECT deptno, SUM(salary) FROM employees@SJMM WHERE status = ? GROUP BY deptno """; try (Connection conn = dataSource.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, "ACTIVE"); try (ResultSet rs = ps.executeQuery()) { while (rs.next()) { int deptno = rs.getInt("deptno"); double totalSalary = rs.getDouble("SUM_SALARY"); System.out.println(deptno + ": " + totalSalary); } } } catch (SQLException e) { System.err.println("SQL Error: " + e.getMessage()); System.err.println("SQL State: " + e.getSQLState()); System.err.println("Error Code: " + e.getErrorCode()); // -937 } ``` --- ### 💡 总结解决步骤: 1. 检查出错的 SQL 语句(可在 `PRC_WT_AA_TTF` 存储过程第 189 行找到)。 2. 查看是否使用了聚合函数(如 `SUM`, `COUNT`)但未对非聚合字段进行 `GROUP BY`。 3. 确保所有非聚合列都在 `GROUP BY` 中。 4. 若涉及 DB Link(`@SJMM`),尽量让聚合发生在远程端或简化逻辑。 5. 使用工具(如 PL/SQL Developer、Toad)测试该 SQL 是否能独立运行。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值