【问题标题】:Oracle throws Not a group by expressionOracle 抛出 Not a group by 表达式
【发布时间】:2015-10-14 13:39:29
【问题描述】:

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

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 错误代码:979

我的查询有什么问题?

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    在您的查询中,问题是最后一条语句 (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)
    

    确实,have 也应该应用于 group by 中包含的字段,而 不是DD.ID 的情况。 所以甲骨文抱怨(现在更清楚)消息“(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 子句的一个很好的解释。

    【讨论】:

      【解决方案2】:

      您似乎想要所有介于最小值和最大值之间的日期值,即使是那些没有匹配值的日期值。我猜每年和每周的聚合只会从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;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-26
        • 2022-01-22
        • 1970-01-01
        • 2017-09-21
        • 2011-08-14
        • 2021-09-12
        • 1970-01-01
        • 2011-06-04
        相关资源
        最近更新 更多