接收 DB2 中列 SUM 的不同输出

Posted

技术标签:

【中文标题】接收 DB2 中列 SUM 的不同输出【英文标题】:Receiving different output for column SUMs in DB2 【发布时间】:2021-08-12 09:18:28 【问题描述】:

我在 DB2 中有下表:

COLUMN_NAME DATA_TYPE TYPE_NAME COLUMN_SIZE COLUMN_TEXT
DMPROD -2 CHAR () FOR BIT DATA 35 Product Code
DMPTYP -2 CHAR () FOR BIT DATA 1 Period Type
DMTYPE -2 CHAR () FOR BIT DATA 6 Type of Data
DMVL01 3 DECIMAL 17 Value Period 1
DMVL02 3 DECIMAL 17 Value Period 2
DMVL03 3 DECIMAL 17 Value Period 3
DMVL04 3 DECIMAL 17 Value Period 4
DMVL05 3 DECIMAL 17 Value Period 5
DMVL06 3 DECIMAL 17 Value Period 6
DMVL07 3 DECIMAL 17 Value Period 7
DMVL08 3 DECIMAL 17 Value Period 8
DMVL09 3 DECIMAL 17 Value Period 9
DMVL10 3 DECIMAL 17 Value Period 10
DMVL11 3 DECIMAL 17 Value Period 11
DMVL12 3 DECIMAL 17 Value Period 12
DMYEAR 3 DECIMAL 4 Fiscal Year

下面的查询将返回每个周期类型的价值周期总和,并将它们分组到产品代码中

SELECT
    D.DMPROD,
    Sum(D.DMVL01 + D.DMVL02 + D.DMVL03 + D.DMVL04 + D.DMVL05 + D.DMVL06) AS Total
FROM
        DWM D
WHERE
        D.DMYEAR IN (2022)
    AND D.DMPTYP = 'M'
    AND D.DMTYPE IN ('RTNQTY','SLSQTY')
GROUP BY
        D.DMPROD
ORDER BY
    1;

初始输出:

DMPROD TOTAL
11105 1145.75000
11350 625.37400
13135 2270.50000
13282 -0.27500
13344 -1.03300
15105 784

然后,由于其他成员的反馈,我将其更改为使用子查询。这是首选格式:

SELECT
    D.DMPROD,
    (SLSQTY + RTNQTY) AS Total
FROM
    (
    SELECT
        D.DMPROD,
        Sum(CASE WHEN D.DMTYPE = 'RTNQTY' THEN Total END) AS RTNQTY,
        Sum(CASE WHEN D.DMTYPE = 'SLSQTY' THEN Total END) AS SLSQTY
    FROM
        (
        SELECT
            D.*,
            (D.DMVL01 + D.DMVL02 + D.DMVL03 + D.DMVL04 + D.DMVL05 + D.DMVL06) AS Total
        FROM
            DWM AS D
    ) AS D
    WHERE
        D.DMYEAR IN (2022)
        AND D.DMPTYP = 'M'
    GROUP BY
        D.DMPROD
) AS D
ORDER BY 1;

但请注意总和不一样(初始输出是正确的):

DMPROD TOTAL
11105 1145.75000
11350 625.37400
13135 2270.50000
13282
13344
15105

我在哪里犯了错误?

【问题讨论】:

很可能 SLSQTY 或 RTNQTY 为 null ,试试coalesce(SLSQTY, 0) + coalesce(RTNQTY, 0) 【参考方案1】:

这些表达方式:

    Sum(CASE WHEN D.DMTYPE = 'RTNQTY' THEN Total END) AS RTNQTY,
    Sum(CASE WHEN D.DMTYPE = 'SLSQTY' THEN Total END) AS SLSQTY

如果结果中没有DMTYPE 的行,则可以返回NULL。这反过来又会影响这个计算:

(SLSQTY + RTNQTY) AS Total

最简单的解决方案是添加ELSE 0:

    Sum(CASE WHEN D.DMTYPE = 'RTNQTY' THEN Total ELSE 0 END) AS RTNQTY,
    Sum(CASE WHEN D.DMTYPE = 'SLSQTY' THEN Total ELSE 0 END) AS SLSQTY

这样就避免了NULL的值,所以总的计算不会变成NULL

【讨论】:

我认为它可能是 NULL,谢谢,确认这个作品【参考方案2】:

可能存在某些DMPROD 组不包含带有某些DMTYPE 的行的情况。此类型的 SUM 为 NULL,如果在 + 运算符中使用此类值,则结果为 NULL。 您可以按原样检查以下示例:

SELECT
  DMPROD
, RTNQTY
, SLSQTY
, RTNQTY + SLSQTY AS TOTAL_new 
, TOTAL_orig
, COALESCE (RTNQTY, 0) + COALESCE (SLSQTY, 0) AS TOTAL_mustbe 
FROM
(
SELECT
  DMPROD
, SUM (CASE WHEN DMTYPE = 'RTNQTY' THEN Total END) AS RTNQTY
, SUM (CASE WHEN DMTYPE = 'SLSQTY' THEN Total END) AS SLSQTY
, SUM (Total) AS TOTAL_orig
FROM 
(
VALUES
  (1, 'RTNQTY', 1)
, (1, 'SLSQTY', 1)
, (2, 'RTNQTY', 1)
) MY_TAB (DMPROD, DMTYPE, Total)
GROUP BY DMPROD
);

结果是:

DMPROD RTNQTY SLSQTY TOTAL_NEW TOTAL_ORIG TOTAL_MUSTBE
1 1 1 2 2 2
2 1 1 1

【讨论】:

以上是关于接收 DB2 中列 SUM 的不同输出的主要内容,如果未能解决你的问题,请参考以下文章

用java实现从命令行接收多个数字,求和之后输出结果。

通过 REST 在两个不同服务器上的两个数据库之间接收数据

课程作业01: 模仿JavaAppArguments.java示例,编写一个程序,此程序从命令行接收多个数字,求和之后输出结果。

模仿JavaAppArguments.java示例,编写一个程序,此程序从命令行接收多个数字,求和之后输出结果。

用java实现从命令行接收多个数字,求和之后输出结果

从命令行接收多个数字,求和之后输出结果