在一对多关系中获得准确的边距DB2

时间:2016-07-21 23:07:48

标签: db2 one-to-many

TLORDER_ALL是一种货件汇总表。它将向分配给此货件的所有承运商提供Total Payable,并且Total Payable记录在INT_PAYABLE_AMT字段中。

另一方面,ORDER_INTERLINER_ALL表将列出从TLORDER_ALL表分配给货件的每个承运人的应付款。 TLORDER_ALL和ORDER_INTERLINER_ALL之间基本上有1对多的关系。支付给每家运营商的款项记录在ORDER_INTERLINER_ALL表的AMOUNT字段中。如果在交付后,会计决定调整应付给承运人的款项,则调整后应付给承运人的记录在ORDER_INTERLINER_ALL表的ADJUSTED_AMOUNT中。如果没有调整,则ADJUSTED_AMOUNT = AMOUNT。

请注意,分配给货件的每个承运人可能有不同的货币要支付,因此这是我使用INT_PAYABLE_AMT * ADJUSTED_AMOUNT / AMOUNT进行转换后通过会计进行转换的原因,因为INT_PAYABLE_AMT以与CHARGES(收入)字段相同的货币记录在TLORDER_ALL表中。

Long Store short,您可能有一个装有Revenue(CHARGES字段)的美元和多个带有CAD和/或USD货币的运营商。应付总额(INT_PAYABLE_AMT)在转换后以与收入(CHARGES)字段相同的货币(USD)记录。最重要的是,您修改后的应付运营商(我们称之为INT_PAYABLE_ADJUST_AMT)可能与INT_PAYABLE_AMT不同。

这是我的摘要查询:

`SELECT 
T.CUSTOMER,
T.CALLNAME,
COUNT(T.BILL_NUMBER) LOADS,
SUM(T.CHARGES+T.XCHARGES)TOTAL_REVENUE,
(SUM(T.CHARGES+T.XCHARGES)-SUM(T.INT_PAYABLE_AMT) *SUM(O.ADJUSTED_AMOUNT) /SUM(O.AMOUNT)) MARGIN
FROM TLORDER_ALL T
INNER JOIN ORDER_INTERLINER_ALL O ON O.DETAIL_LINE_ID=T.DETAIL_LINE_ID
WHERE T.INT_PAYABLE_AMT<>0
AND T.CHARGES+T.XCHARGES<>0
AND T.CUSTOMER='117990'
AND O.INTERFACE_STATUS='I'
AND O.AMOUNT<>0
GROUP BY T.CUSTOMER,T.CALLNAME`

This is output image

这是我的详细信息查询

SELECT 
T.DETAIL_LINE_ID,
T.BILL_NUMBER,
T.CUSTOMER,
T.CALLNAME,
(T.CHARGES+T.XCHARGES)TOTAL_REVENUE,
(T.CHARGES+T.XCHARGES-T.INT_PAYABLE_AMT *O.ADJUSTED_AMOUNT /O.AMOUNT) MARGIN,
T.INT_PAYABLE_AMT,
O.ADJUSTED_AMOUNT,
O.AMOUNT,
O.INTERFACE_STATUS
FROM TLORDER_ALL T
INNER JOIN ORDER_INTERLINER_ALL O ON O.DETAIL_LINE_ID=T.DETAIL_LINE_ID
WHERE T.INT_PAYABLE_AMT<>0
AND T.CHARGES+T.XCHARGES<>0
AND YEAR(T.DELIVER_BY)= YEAR(CURRENT DATE) 
AND MONTH(T.DELIVER_BY)=MONTH(CURRENT DATE)-1
AND T.CUSTOMER='117990'
AND O.INTERFACE_STATUS='I'
AND O.AMOUNT<>0

This is the output image

我的问题是如何消除相同货件的多个条目,因为货件有多个承运人,并且能够在汇总和明细输出中获得准确的最终保证金?

如果我们回顾详细信息图片,我希望得到5条记录而不是14条记录并汇总所有运营商应付款,使用INT_PAYABLE_AMT * ADJUSTED_AMOUNT / AMOUNT转换它,并从这5条记录的每一行减去TOTAL_REVENUE。应用相同的逻辑以在Summary输出中获得准确的结果。

谢谢。

1 个答案:

答案 0 :(得分:0)

好的,你的摘要是正确的,使CTE然后一步一步地操纵它 (注意我在第一个CTE中留下所有行 - 这使得调试变得容易,注释掉所有内容并在每个步骤后添加一个选择验证值):

WITH Detail AS
(
  SELECT 
    T.DETAIL_LINE_ID,
    T.BILL_NUMBER,
    T.CUSTOMER,
    T.CALLNAME,
    (T.CHARGES+T.XCHARGES)TOTAL_REVENUE,
    (T.CHARGES+T.XCHARGES-T.INT_PAYABLE_AMT *O.ADJUSTED_AMOUNT /O.AMOUNT)  MARGIN,
    T.INT_PAYABLE_AMT,
    O.ADJUSTED_AMOUNT,
    O.AMOUNT,
    O.INTERFACE_STATUS
  FROM TLORDER_ALL T
  INNER JOIN ORDER_INTERLINER_ALL O ON O.DETAIL_LINE_ID=T.DETAIL_LINE_ID
  WHERE T.INT_PAYABLE_AMT<>0
    AND T.CHARGES+T.XCHARGES<>0
    AND YEAR(T.DELIVER_BY)= YEAR(CURRENT DATE) 
    AND MONTH(T.DELIVER_BY)=MONTH(CURRENT DATE)-1
    AND T.CUSTOMER='117990'
    AND O.INTERFACE_STATUS='I'
    AND O.AMOUNT<>0
), C_COMBINE AS
(
  -- Here we combine the amounts for each leg
  SELECT
    DETAIL_LINE_ID,
    CUSTOMER,
    -- Payable amt and customer are always the same, just pick one.
    MAX(INT_PAYABLE_AMT) AS INT_PAYABLE_AMT,
    SUM(ADJUSTED_AMOUNT) AS SUM_ADJUSTED_AMOUNT,
    SUM(AMOUNT) AS SUM_AMOUNT
  FROM Detail
  GROUP BY DETAIL_LINE_ID, CUSTOMER
), ADJ_FOR_CURRENCY
(
  SELECT 
    DETAIL_LINE_ID,
    CUSTOMER,
    INT_PAYABLE_AMT * (SUM_ADJUSTED_AMOUNT/SUM_AMOUNT) AS AMOUNT
  FROM C_COMBINE
)
-- Now do what you want... roll up by customer?
SELECT 
  CUSTOMER,
  SUM(AMOUNT) AS TOTAL_FOR_CUSTOMER
GROUP BY CUSTOMER

是的,通过将步骤合并为一个,可以用更少的线和更少的CTE来编写。但后来很难理解和写作。像这样很明显,你可以添加评论和测试。例如,如果数字未正确显示,则将选择更改为SELECT * FROM C_COMBINE并验证步骤是否正常工作。

另外,如果你使用一个不错的优化服务器(并且db2是最好的或者在顶级的IMO中 - 我为IBM工作所以我可能有偏见)以这种方式使用CTE通常会允许编译器生成根据我的经验,更快的执行计划。

祝你好运。