SQL聚合函数失败

时间:2014-05-09 11:15:57

标签: sql oracle aggregate-functions

我遇到了一种我无法诊断的奇怪行为。

我有一个Oracle数据库(11g),我在这个数据库中构建了一个视图。此视图返回一个信息列表,该信息列表在问题发生前没有问题,并且在问题发生之后目前处于罚款状态。

假设此视图返回10行。当我在此视图上运行聚合函数时,例如让我们说一个COUNT(*)我得到一个10行的列表,每行显示'Null'而不是一行,数字为10.

这是一个突然开始的问题,没有我故意改变数据库或视图(但这是一个大型企业数据库,并且可能由少数其他人做出改变 - 所有这些当前都否认任何已做出更改)也没有影响视图的已知触发器

此问题不会出现在其他表或其他视图中。我已经尝试在构成最终视图的每个表或视图上运行聚合函数,并且每个表都按预期返回一个数字。

我不确定还有什么可以尝试的。我的Google搜索也没有提供任何线索。我会上传代码,但它很大而且笨重,我也无法开始解释它是如何查看数据的(足以说数据库是法语构建的)

真正让我感到的是视图按预期返回数据,但当我在其上运行聚合函数时(例如SELECT COUNT(*)FROM VIEW_THAT_IS_FAILING),它以这种奇怪的方式失败。有什么想法吗?

查看定义失败:

SELECT x.OBJEXCDE,
       x.OBJDSC,
       x.CLASSIFICATION,
       x.COUNTRY,
       NVL(y.MONTH_USAGE, 0) AS MONTH_USAGE,
       x.STKQTY,
       x.STANDARD_COST

    FROM (SELECT a.OBJINCDE, a.OBJEXCDE, a.OBJDSC, NVL(b.STKQTY, 0) AS STKQTY, NVL(c.OBJPRC1VAL, 0) AS STANDARD_COST, NVL(d.OBJCHARVAL, 'Exception') AS CLASSIFICATION,
                 CASE WHEN TO_CHAR(b.STOREINCDE, '0000') || TO_CHAR(c.OBJRTEINCDE, '000') =  ' 0615 130' THEN 'UK'
                      ELSE 'IRE' END AS COUNTRY             
             FROM P_OBJ a, P_OBJSTORE b, P_OBJPRC c,
                  (SELECT a.OBJINCDE, b.OBJCHARVAL
                      FROM P_OBJ a, (SELECT OBJINCDE, OBJCHARVAL FROM P_OBJCHAR WHERE CHARINCDE = 524) b
                      WHERE a.OBJINCDE = b.OBJINCDE (+)) d             
             WHERE a.OBJINCDE = b.OBJINCDE (+)
             AND a.OBJINCDE = c.OBJINCDE (+)
             AND a.OBJINCDE = d.OBJINCDE (+)
             AND TO_CHAR(b.STOREINCDE, '0000') || TO_CHAR(c.OBJRTEINCDE, '000') IN (' 0615 130', ' 1158 284')
             AND a.CLASSINCDE IN (83, 84, 126)  --New Parts, Repairable Parts, Installation Parts
             AND (d.OBJCHARVAL IS NULL OR NVL(c.OBJPRC1VAL, 0) = 0)) x,
         W_USAGE_1_MONTH y

    WHERE x.OBJINCDE = y.OBJINCDE (+)
    AND x.COUNTRY = y.COUNTRY (+)

    AND (NVL(y.MONTH_USAGE, 0) + x.STKQTY) > 0

W_USAGE_1_MONTH的定义:

SELECT a.OBJINCDE, 
       a.OBJEXCDE, 
       a.OBJDSC, 
       NVL(b.STKQTY, 0) AS STKQTY, 
       NVL(c.OBJPRC1VAL, 0) AS STANDARD_COST, 
       NVL(d.OBJCHARVAL, 'Exception') AS CLASSIFICATION,
       CASE WHEN TO_CHAR(b.STOREINCDE, '0000') || TO_CHAR(c.OBJRTEINCDE, '000') =  ' 0615 130' THEN 'UK' ELSE 'IRE' END AS COUNTRY             

    FROM P_OBJ a, 
         P_OBJSTORE b, 
         P_OBJPRC c,
         (SELECT a.OBJINCDE, b.OBJCHARVAL FROM P_OBJ a, (SELECT OBJINCDE, OBJCHARVAL FROM P_OBJCHAR WHERE CHARINCDE = 524) b WHERE a.OBJINCDE = b.OBJINCDE (+)) d             

    WHERE a.OBJINCDE = b.OBJINCDE (+)
    AND a.OBJINCDE = c.OBJINCDE (+)
    AND a.OBJINCDE = d.OBJINCDE (+)
    AND TO_CHAR(b.STOREINCDE, '0000') || TO_CHAR(c.OBJRTEINCDE, '000') IN (' 0615 130', ' 1158 284')
    AND a.CLASSINCDE IN (83, 84, 126)  --New Parts, Repairable Parts, Installation Parts
    AND (d.OBJCHARVAL IS NULL OR NVL(c.OBJPRC1VAL, 0) = 0)

2 个答案:

答案 0 :(得分:0)

只是为了好玩,请尝试以下方法:

SELECT x.OBJEXCDE,
       x.OBJDSC,
       x.CLASSIFICATION,
       x.COUNTRY,
       NVL(y.MONTH_USAGE, 0) AS MONTH_USAGE,
       x.STKQTY,
       x.STANDARD_COST
  FROM (SELECT a.OBJINCDE,
               a.OBJEXCDE,
               a.OBJDSC,
               NVL(b.STKQTY, 0) AS STKQTY,
               NVL(c.OBJPRC1VAL, 0) AS STANDARD_COST,
               NVL(d.OBJCHARVAL, 'Exception') AS CLASSIFICATION,
               CASE
                 WHEN TO_CHAR(b.STOREINCDE, '0000') || TO_CHAR(c.OBJRTEINCDE, '000') =  ' 0615 130' THEN 'UK'
                 ELSE 'IRE'
               END AS COUNTRY             
           FROM P_OBJ a
           LEFT OUTER JOIN P_OBJSTORE b
             ON (a.OBJINCDE = b.OBJINCDE)
           LEFT OUTER JOIN P_OBJPRC c
             ON (a.OBJINCDE = c.OBJINCDE)
           LEFT OUTER JOIN (SELECT a.OBJINCDE, b.OBJCHARVAL
                              FROM P_OBJ a
                              LEFT OUTER JOIN (SELECT OBJINCDE, OBJCHARVAL
                                                 FROM P_OBJCHAR
                                                 WHERE CHARINCDE = 524) b
                                ON (a.OBJINCDE = b.OBJINCDE)) d
             ON (a.OBJINCDE = d.OBJINCDE)
          WHERE TO_CHAR(b.STOREINCDE, '0000') || TO_CHAR(c.OBJRTEINCDE, '000') IN (' 0615 130', ' 1158 284') AND
                a.CLASSINCDE IN (83, 84, 126) AND --New Parts, Repairable Parts, Installation Parts
                (d.OBJCHARVAL IS NULL OR
                NVL(c.OBJPRC1VAL, 0) = 0)) x
  LEFT OUTER JOIN W_USAGE_1_MONTH y
    ON (x.OBJINCDE = y.OBJINCDE AND
        x.COUNTRY = y.COUNTRY)
  WHERE (NVL(y.MONTH_USAGE, 0) + x.STKQTY) > 0

这只是使用ANSI连接语法重新编写的原始视图。试一试,看看它是否有所改变。

也可能是DBA应用了补丁或进行了其他一些影响这一点的变化。

分享并享受。

答案 1 :(得分:0)

虽然支持请求仍然没有得到回应,但我还是弄清楚了解这个问题。

虽然打破视图回到它的基本要素,但我发现当我试图对较小的聚合部分进行聚合时,SQL失败了。因此,W_USAGE_1_MONTH中的聚合导致较大的少数聚合失败,其方式是将一系列NULL值放入多少行的计数,而不是一行计算行数。

虽然我对视图进行了一些修补,但是当我在FROM Clause Select语句中封装了W_USAGE_1_MONTH时,行为似乎已经解决了:

(SELECT OBJINCDE, MONTH_USAGE, COUNTRY FROM W_USAGE_1_MONTH) b

我的感觉是,DBA(我没有立即访问权限)进行了一项更改,这会对处理SQL语句的顺序产生影响。强制在语句使用W_USAGE_1_MONTH视图之前对其进行评估,从而导致操作成功完成。

对于一个奇怪的事件和一个不能解释根本原因的答案来说,这不是一个非常令人兴奋的结局,因为我不知道可能产生哪些影响评估顺序的变化。但是,这可能会帮助其他人查看奇怪行为的评估顺序。

相关问题