Oracle不按表达式抛出组

时间:2015-10-14 13:39:30

标签: sql oracle

我有一个查询,我使用一个右边连接日期表的表,这意味着我得到所有日期值。我只想在表格结果集的边框之间设置值。我有以下查询

Select DD.CAL_YEAR, DD.WEEK_OF_YEAR, Count(Distinct FPP.ID) As Total
From FACT_PAY_PAYMENT FPP
    Right Join DIM_DATE DD On FPP.REQUESTED_EXECUTION_DATE_ID = DD.ID
Group By DD.CAL_YEAR, DD.WEEK_OF_YEAR
Having DD.ID >= MIN(FPP.REQUESTED_EXECUTION_DATE_ID)
   AND DD.ID <= MAX(FPP.REQUESTED_EXECUTION_DATE_ID);

但是当我执行此操作时,我收到来自Oracle的错误

  

错误:ORA-00979:不是GROUP BY表达式

     

SQLState:42000 ErrorCode:979

我的查询有什么问题?

2 个答案:

答案 0 :(得分:3)

在您的查询中,问题是最后一个语句(having):

Select DD.CAL_YEAR, DD.WEEK_OF_YEAR, Count(Distinct FPP.ID) As Total
    From FACT_PAY_PAYMENT FPP
    Right Join DIM_DATE DD On FPP.REQUESTED_EXECUTION_DATE_ID = DD.ID
    Group By DD.CAL_YEAR,DD.WEEK_OF_YEAR
--->        Having DD.ID >= MIN(FPP.REQUESTED_EXECUTION_DATE_ID) AND DD.ID <= MAX(FPP.REQUESTED_EXECUTION_DATE_ID)

确实,也应该应用于group by中包含的字段,并且不是 DD.ID的情况。 所以Oracle抱怨(现在更清楚)消息“(DD.ID is)not(in)a group by expression

如果与您的业务逻辑兼容,可能的解决方案可能是将您的having子句转换为简单的where子句:

Select DD.CAL_YEAR, DD.WEEK_OF_YEAR, Count(Distinct FPP.ID) As Total
    From FACT_PAY_PAYMENT FPP
    Right Join DIM_DATE DD On FPP.REQUESTED_EXECUTION_DATE_ID = DD.ID
    Where DD.ID >= ... 
    And DD.ID <= ...
    Group By DD.CAL_YEAR,DD.WEEK_OF_YEAR

Here您可以找到having vs where子句的精彩解释。

答案 1 :(得分:0)

您似乎想要所有 min和max之间的日期值,即使是没有匹配值的日期值。我猜测按年份和年份的汇总只会从DD获得少量ID。所以,一种方法是:

Select DD.CAL_YEAR, DD.WEEK_OF_YEAR, Count(Distinct FPP.ID) As Total
From DIM_DATE DD LEFT JOIN
     FACT_PAY_PAYMENT FPP
     On FPP.REQUESTED_EXECUTION_DATE_ID = DD.ID
Group By DD.CAL_YEAR, DD.WEEK_OF_YEAR
Having MAX(DD.ID) >= MIN(FPP.REQUESTED_EXECUTION_DATE_ID) AND
       MIN(DD.ID) <= MAX(FPP.REQUESTED_EXECUTION_DATE_ID);

但是,在HAVING子句中进行此过滤是浪费精力 - 查询已经聚合了所有内容。这是一种在WHERE中获取它的方法:

Select DD.CAL_YEAR, DD.WEEK_OF_YEAR, Count(Distinct FPP.ID) As Total
From DIM_DATE DD LEFT JOIN
     FACT_PAY_PAYMENT FPP
     On FPP.REQUESTED_EXECUTION_DATE_ID = DD.ID CROSS JOIN
     (SELECT MIN(FPP.REQUESTED_EXECUTION_DATE_ID) as minredi,
             MAX(FPP.REQUESTED_EXECUTION_DATE_ID) as maxredi
      FROM FACT_PAY_PAYMENT
     ) minmax
Where DD.ID >= minmax.minredi AND DD.ID <= minmax.maxredi
Group By DD.CAL_YEAR, DD.WEEK_OF_YEAR;