在一对多关系DB2中获得准确的利润

在一对多关系DB2中获得准确的利润,db2,one-to-many,Db2,One To Many,TLORDER_ALL是一种装运的汇总表。它将提供分配给此装运的所有承运商的应付总额,应付总额记录在“应付国际金额”字段中 另一方面,ORDER_INTERLINER_ALL表将列出从TLORDER_ALL表分配给装运的每个承运人的应付款项。基本上,TLORDER\u ALL和ORDER\u INTERLINER\u ALL之间有1对多的关系。支付给每个承运人的款项记录在订单_INTERLINER _ALL表的金额字段中。如果在交货后,会计部门决定调整应付给承运人的款项,则调整后的应付给承运人的

TLORDER_ALL是一种装运的汇总表。它将提供分配给此装运的所有承运商的应付总额,应付总额记录在“应付国际金额”字段中

另一方面,ORDER_INTERLINER_ALL表将列出从TLORDER_ALL表分配给装运的每个承运人的应付款项。基本上,TLORDER\u ALL和ORDER\u INTERLINER\u ALL之间有1对多的关系。支付给每个承运人的款项记录在订单_INTERLINER _ALL表的金额字段中。如果在交货后,会计部门决定调整应付给承运人的款项,则调整后的应付给承运人的款项将记录在ORDER\u INTERLINER\u ALL表中的调整金额中。如果没有调整,则调整金额=金额

请注意,分配给装运的每个承运商可能有不同的支付货币,这就是我使用INT_Payment_AMT*ADJUSTED_AMOUNT/金额进行会计调整后进行转换的原因,因为INT_Payment_AMT与TLORDER_ALL表格中的费用(收入)字段以相同的货币记录

长仓短仓,您可能有一批收入(费用字段)为美元的货物,以及多家以CAD和/或美元货币的承运人。转换后,应付总额(应付金额)以与收入(费用)字段相同的货币(美元)记录。最重要的是,您修改后的应付承运人金额(我们称之为应付国际金额)可能与应付国际金额不同

这是我的摘要查询:

`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`
`选择
T.CUSTOMER,
T.CALLNAME,
计数(T.BILL_编号)荷载,
总收入(T.费用+T.X费用),
(总额(T.费用+T.X费用)-总额(T.INT应付金额)*总额(O.调整金额)/总额(O.金额))保证金
从TLT订购
内部连接顺序\u中间行\u所有O上O.DETAIL\u LINE\u ID=T.DETAIL\u LINE\u ID
其中T.INT\u应付金额为
和T.CHARGES+T.XCHARGES0
和T.CUSTOMER='117990'
和O.INTERFACE_STATUS='I'
和O.AMOUNT0
按T.CUSTOMER、T.CALLNAME分组`

这是我的详细信息查询

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
选择
T.细节线ID,
T.BILL_编号,
T.CUSTOMER,
T.CALLNAME,
(T.CHARGES+T.XCHARGES)总收入,
(T.CHARGES+T.XCHARGES-T.INT\u应付金额*O.ADJUSTED\u金额/O.AMOUNT)保证金,
T.INT应付金额,
O.调整后的金额,
O.金额,
O.接口状态
从TLT订购
内部连接顺序\u中间行\u所有O上O.DETAIL\u LINE\u ID=T.DETAIL\u LINE\u ID
其中T.INT\u应付金额为
和T.CHARGES+T.XCHARGES0
年份(T.DELIVER_BY)=年份(当前日期)
月(T.DELIVER_BY)=月(当前日期)-1
和T.CUSTOMER='117990'
和O.INTERFACE_STATUS='I'
和O.AMOUNT0

我的问题是,我如何消除同一批货物的多个条目,因为该批货物有多个承运人,并且能够在摘要和详细信息输出中获得准确的最终利润

如果我们回顾详细信息图像,我希望得到5条记录,而不是14条记录,并将所有承运商应付款项相加,使用INT_Payment_AMT*ADJUSTED_AMOUNT/AMOUNT将其转换,并从这5条记录的每一行的总收入中减去。应用相同的逻辑也可以在摘要输出中获得准确的结果


谢谢。

好的,您的总结是正确的,请检查CTE,然后逐步操作它 (注意,我保留了第一个CTE中的所有行——这使得调试、注释之后的所有内容以及在每个步骤之后添加选择验证值变得容易):

详细信息如下:
(
挑选
T.细节线ID,
T.BILL_编号,
T.CUSTOMER,
T.CALLNAME,
(T.CHARGES+T.XCHARGES)总收入,
(T.CHARGES+T.XCHARGES-T.INT\u应付金额*O.ADJUSTED\u金额/O.AMOUNT)保证金,
T.INT应付金额,
O.调整后的金额,
O.金额,
O.接口状态
从TLT订购
内部连接顺序\u中间行\u所有O上O.DETAIL\u LINE\u ID=T.DETAIL\u LINE\u ID
其中T.INT\u应付金额为
和T.CHARGES+T.XCHARGES0
年份(T.DELIVER_BY)=年份(当前日期)
月(T.DELIVER_BY)=月(当前日期)-1
和T.CUSTOMER='117990'
和O.INTERFACE_STATUS='I'
和O.AMOUNT0
),C_组合为
(
--在这里,我们结合了每条腿的数量
挑选
细节线ID,
顾客
--应付金额和客户始终相同,只需选择一个即可。
最大(应付国际金额)作为应付国际金额,
总额(调整金额)作为总额调整金额,
总和(金额)作为总和
从细节
按详细信息分组\u行\u ID,客户
),调整为货币
(
挑选
细节线ID,
顾客
应付金额*(调整金额/调整金额)作为金额
从C_联合收割机
)
--现在做你想做的。。。按客户汇总?
挑选
顾客
总金额(金额)为客户的总金额
按客户分组
是的,这一切都可以用更少的行和更少的CTE来写——通过将步骤组合成一个步骤。但后来,理解和写作变得非常困难。很明显,您可以添加注释和测试。例如,如果数字显示不正确,请将选择更改为从C_COMBINE选择*并验证步骤是否正常工作

此外,如果您使用的是一个不错的优化服务器(db2是最好的,或者是我在IBM工作过的顶级服务器,所以我可能会有偏见),以这种方式使用CTE通常会让编译器根据我的经验制定出更快的执行计划


祝您好运。

您的格式设置使问题难以理解,但您收到的错误消息似乎很清楚。如果没有
分组依据
,则不能使用
SUM
。以这种方式编写的子查询往往每行执行一次,从而影响性能(尽管如果只查询单个帐户,则可能不会太大)。您的查询当前有一个问题-如果每个详细信息行有多个
接口\u状态
行,它将“随机”且无声地丢弃一个,几乎肯定不是您想要的。您将四舍五入到两个不同的小数位。一些示例数据将有助于了解如何更好地构造此查询。您好,不存在“o”table和group by子句来执行求和agregate。。。
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