我有一个查询,我使用一个右边连接日期表的表,这意味着我得到所有日期值。我只想在表格结果集的边框之间设置值。我有以下查询
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
我的查询有什么问题?
答案 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;