为什么这个百分比总和不能达到100%?

时间:2011-07-06 12:06:22

标签: sql db2 sum

我在DB2 SQL DB中有一系列计算时间,这些计算时间存储为float,默认值为0.0。

正在更新的表格如下:

CREATE TABLE MY_CALC_DATA_TABLE
(
    CALCDATE                 TIMESTAMP,
    INDIV_CALC_DURATION_IN_S FLOAT WITH DEFAULT 0.0,
    CALC_TIME_PERCENTAGE     FLOAT WITH DEFAULT 0.0
)

使用sproc。我按如下方式计算总和:

CREATE OR REPLACE PROCEDURE MY_SCHEMA.MY_SPROC (IN P_DATE TIMESTAMP)
    LANGUAGE SQL
    NO EXTERNAL ACTION
BEGIN
    DECLARE V_TOTAL_CALC_TIME_IN_S FLOAT DEFAULT 0.0;

    -- other stuff setting up and joining data

    -- Calculate the total time taken to perform the
    -- individual calculations

    SET V_TOTAL_CALC_TIME_IN_S =
        (
            SELECT
                SUM(C.INDIV_CALC_DURATION_IN_S)
            FROM
                MY_SCHEMA.MY_CALC_DATA_TABLE C
            WHERE
                C.CALCDATE = P_DATE
        )

    -- Now calculate each individual calculation's percentage
    -- of the toal time.

    UPDATE
        MY_SCHEMA.MY_CALC_DATA_TABLE C
    SET
        C.CALC_TIME_PERCENTAGE =
            (C.INDIV_CALC_DURATION_IN_S / V_TOTAL_CALC_TIME_IN_S) * 100
    WHERE
        C.CALCDATE = P_DATE;

END@

麻烦的是,当我对指定的CALC_DATE的所有CALC_TIME_PERCENTAGE值求和时,它总是小于100%,对于不同的CALC_DATES,总和为80%或70%的值。

我们在这里讨论的是35k和55k之间的计算,其中最大单个计算的总百分比(如上所计算)为12%,批次的计算范围为0.00000N%。

要计算我使用简单查询的总百分比:

SELECT
    SUM(C.CALC_TIME_PERCENTAGE)
FROM
    MY_SCHEMA.MY_CALC_DATA_TABLE C
WHERE
    C.CALCDATE = P_DATE;

有什么建议吗?

更新:重新排列计算结果。建议修复问题。谢谢。 BTW在DB2中,FLOAT和DOUBLE是相同的类型。现在阅读有关花车的建议论文。

3 个答案:

答案 0 :(得分:3)

如果字段C.INDIV_CALC_DURATION_IN_S是整数,我会认为这是一个舍入错误。再次阅读,这不是问题,因为数据类型是FLOAT

你仍然可以尝试使用它。如果这与前一种方法的结果差不多(略有不同),我不会感到惊讶:

SET
    C.CALC_TIME_PERCENTAGE =
        (C.INDIV_CALC_DURATION_IN_S * 100.0 / V_TOTAL_CALC_TIME_IN_S)

但是你提到某个日期的计算中有很多行,因此它可能是一个舍入错误。尝试在两个字段(或至少DOUBLE字段)中使用CALC_TIME_PERCENTAGE数据类型,看看与100%之间的差异是否会变小。

我不确定DB2是否有DECIMAL(x,y)数据类型。在这种情况下可能更合适。


另一个问题是如何找到CALC_TIME_PERCENTAGE的总和。我想你(以及其他所有人)会使用:

        SELECT
            P_DATE, SUM(CALC_TIME_PERCENTAGE)
        FROM
            MY_SCHEMA.MY_CALC_DATA_TABLE C
        GROUP BY P_DATE

这样,您无法确定求和的顺序。甚至可能无法确定,但您可以尝试:

        SELECT
            P_DATE, SUM(CALC_TIME_PERCENTAGE)
        FROM
          ( SELECT
                P_DATE, CALC_TIME_PERCENTAGE
            FROM
                MY_SCHEMA.MY_CALC_DATA_TABLE C
            ORDER BY P_DATE
                   , CALC_TIME_PERCENTAGE ASC
          ) AS tmp
        GROUP BY P_DATE

优化器可能会忽略内部ORDER BY,但值得一试。


这种巨大差异的另一种可能性是从UPDATESHOW percent SUM操作之间的表中删除行。

您可以通过运行计算(没有UPDATE)并总结来测试是否发生这种情况:

        SELECT
            P_DATE
          , SUM( INDIV_CALC_DURATION_IN_S * 100.0 / T.TOTAL )                   
            AS PERCENT_SUM
        FROM
            MY_SCHEMA.MY_CALC_DATA_TABLE C
          , ( SELECT SUM(INDIV_CALC_DURATION_IN_S) AS TOTAL
              FROM MY_SCHEMA.MY_CALC_DATA_TABLE
            ) AS TMP
        GROUP BY P_DATE

答案 1 :(得分:2)

可能是一个舍入问题。请尝试使用C.INDIV_CALC_DURATION_IN_S * 100 / V_TOTAL_CALC_TIME_IN_S

答案 2 :(得分:1)

如果C.INDIV_CALC_DURATION_IN_S非常小,但您有大量行(因此V_TOTAL_CALC_TIME_IN_S会变大),那么

(C.INDIV_CALC_DURATION_IN_S / V_TOTAL_CALC_TIME_IN_S) * 100

可能会失去精确度,尤其是在您使用FLOAT时。

如果是这种情况,则将计算(如其他地方所述)更改为

(C.INDIV_CALC_DURATION_IN_S * 100) / V_TOTAL_CALC_TIME_IN_S 

应该增加总数,虽然它可能无法让你一直到100%

如果是这种情况并且很多测量都是小部分时间,我会考虑超越这个程序:是否可以记录时间,例如毫秒或微秒?要么为你提供额外的有效数字空间。