ORA-00979不是表达式组

我得到 ORA-00979与以下查询:

SELECT cr.review_sk, cr.cs_sk, cr.full_name,
tolist(to_char(cf.fact_date, 'mm/dd/yyyy')) "appt",
cs.cs_id, cr.tracking_number
from review cr, cs, fact cf
where cr.cs_sk = cs.cs_sk
and UPPER(cs.cs_id) like '%' || UPPER(i_cs_id) || '%'
and row_delete_date_time is null
and cr.review_sk = cf.review_wk (+)
and cr.fact_type_code (+) = 183050
GROUP BY cr.review_sk, cr.cs_sk, cf.fact_date, cr.tracking_number
ORDER BY cs.cs_id, cr.full_name;

我找不到在同一个查询中同时包含 GROUPBY 和 ORDERBY 子句的任何示例。我尝试一次从组中删除一个字段,但仍然得到相同的错误。

546424 次浏览

GROUP BY子句中包含所有不是组函数参数的 SELECT表达式。

您必须将 SELECT的所有列放在 GROUP BY中,或者对它们使用将结果压缩为单个值的函数(如 MINMAXSUM)。

一个简单的例子可以理解为什么会发生这种情况: 假设您有一个这样的数据库:

FOO BAR
0   A
0   B

运行 SELECT * FROM table GROUP BY foo。这意味着数据库必须返回一行结果和第一列 0来实现 GROUP BY,但是现在有两个 bar值可供选择。你期望哪个结果-A还是 B?或者数据库应该返回多行,这违反了 GROUP BY的约定?

可惜甲骨文有这样的局限性。当然,不在 GROUPBY 中的列的结果是随机的,但是有时您希望这样。愚蠢的 Oracle,您可以在 MySQL/MSSQL 中执行此操作。

但甲骨文有一个解决办法:

虽然以下行不工作

SELECT unique_id_col, COUNT(1) AS cnt FROM yourTable GROUP BY col_A;

您可以像下面这样使用一些0来欺骗 Oracle,使您的列保持在作用域中,但是不按它分组(假设这些是数字,否则使用 CONCAT)

SELECT MAX(unique_id_col) AS unique_id_col, COUNT(1) AS cnt
FROM yourTable GROUP BY col_A, (unique_id_col*0 + col_A);

根据聚合函数,分组用于聚合一些数据,除此之外,您还需要将需要分组的列放入其中。

例如:

select d.deptno, max(e.sal)
from emp e, dept d
where e.deptno = d.deptno
group by d.deptno;

这将导致各部门的最高工资。

现在,如果我们从 group by 子句中省略 d.deptno,它将给出相同的错误。

你应该这样做:

SELECT cr.review_sk,
cr.cs_sk,
cr.full_name,
tolist(to_char(cf.fact_date, 'mm/dd/yyyy')) "appt",
cs.cs_id,
cr.tracking_number
from review cr, cs, fact cf
where cr.cs_sk = cs.cs_sk
and UPPER(cs.cs_id) like '%' || UPPER(i_cs_id) || '%'
and row_delete_date_time is null
and cr.review_sk = cf.review_wk (+)
and cr.fact_type_code (+) = 183050
GROUP BY cr.review_sk, cr.cs_sk, cf.fact_date, cr.tracking_number, cs.cs_id, cr.full_name
ORDER BY cs.cs_id, cr.full_name;

如果在选择表达式和逐个表达式中都没有使用 上面低一点关键字,也会出现同样的错误。

错:-

select a , count(*) from my_table group by UPPER(a) .

右:-

select UPPER(a) , count(*) from my_table group by UPPER(a) .

如果你通过包含 GROUP BY子句来进行分组,那么 SELECT中的任何表达式,如 COUNTAVGMINMAXSUM等(聚合函数列表) ,如果不是群函数(或聚合函数或聚合列) ,都应该出现在 GROUP BY子句中。

示例(正确的方式) (这里的 employee_id不是组函数(非聚合列) ,因此它出现在 GROUP BY中。相比之下,sum (pay)是一个组函数(聚合列) ,因此不需要出现在 GROUP BY子句中。

   SELECT employee_id, sum(salary)
FROM employees
GROUP BY employee_id;

示例(错误的方式) (这里的 employee_id不是组函数,它不出现在 GROUP BY子句中,这将导致 ORA-00979错误。

   SELECT employee_id, sum(salary)
FROM employees;

要纠正这个错误,你需要做以下 :

  • 子句中列出的所有非聚合表达式包括在 GROUP BY条款
  • SELECT子句中删除 group (聚合)函数。

除了其他答案之外,如果 by 子句的顺序不一致,也可能导致此错误。例如:

select
substr(year_month, 1, 4)
,count(*) as tot
from
schema.tbl
group by
substr(year_month, 1, 4)
order by
year_month

“ Aaron Digulla”(这是第一个)的答案启发我使用 Spring Boot 2(JPA/Hibernate)和 CriteriaQuery/CriteriaBuilder 解决同样的错误代码。

创建一个选择列表,并将其添加到 CritiaQuery.multiselect ()

List<Selection> selects = new ArrayList<>();
selects.add(seccionRoot.get("id"));
selects.add(synSeccionRoot.get("DDF"));
selects.add(synSeccionRoot.get("TTYU"));
selects.add(synSeccionRoot.get("4567"));
selects.add(seccionRoot.get("22").get("223"));
selects.add(tasaRoot.get("price"));
selects.add(tasaRoot.get("chair"));


cq.multiselect(selects.toArray(Selection[]::new));

然后可以将 List 强制转换为 Expression []

cq.groupBy(selects.toArray(Expression[]::new));

针对每组中的随机行,为 @ Joseph Lust’s答案添加一个替代解决方案。这在 Oracle Database 19c 或更新版本中是通过使用 any_value关键字实现的。这里有一个例子:

select customer_id,
max ( order_datetime ),
any_value ( store_id ),
any_value ( order_status ),
any_value ( order_id )
from   co.orders
group  by customer_id;