字段聚合不能正确地基于联接到另一个表

时间:2019-03-26 00:12:00

标签: sql sql-server sql-server-2014

我在下面的查询中尝试根据G.MERCHANDISE_AMT的总和除以D.MERCHANDISE_AMT的总和来计算百分比。该表中的PO_ID包含2个行号,每个行号具有2个分布,共4行,我得到D.MERCHANDISE_AMT的SUM遍及所有4行。请注意,G.MERCHANDISE_AMT是这两个表PS_PO_LINE_DISTRIB DPS_DISTRIB_LINE G

中的一个字段
SELECT A.BUSINESS_UNIT, A.PO_ID,  A.PO_TYPE, A.PO_STATUS, (CONVERT(CHAR(10),A.PO_DT,121)), A.VENDOR_ID,
A.BUYER_ID, D.DEPTID, SUM(G.MERCHANDISE_AMT) AS 'TOTAL_VCHR_AMT', NULLIF((SUM(G.MERCHANDISE_AMT) / SUM(D.MERCHANDISE_AMT)),0) AS 'Threshold' , E.SETID + '_' +   E.DEPTID AS 'REQUESTOR', H.ROLEUSER_SUPR

FROM PS_PO_LINE_DISTRIB D 
INNER JOIN  PS_PO_LINE C ON  D.BUSINESS_UNIT = C.BUSINESS_UNIT AND D.PO_ID = C.PO_ID AND C.LINE_NBR = D.LINE_NBR
INNER JOIN PS_PO_HDR A ON A.BUSINESS_UNIT = C.BUSINESS_UNIT AND A.PO_ID = C.PO_ID
INNER JOIN  PS_DEPT_TBL E ON  E.DEPTID = D.DEPTID AND E.SETID = D.BUSINESS_UNIT_GL 
INNER JOIN PS_DISTRIB_LINE G ON  G.PO_ID = D.PO_ID AND G.BUSINESS_UNIT_PO = D.BUSINESS_UNIT AND G.LINE_NBR = D.LINE_NBR AND G.SCHED_NBR = D.SCHED_NBR AND G.PO_DIST_LINE_NUM = D.DISTRIB_LINE_NUM
INNER JOIN PS_ROLEXLATOPR H ON H.ROLEUSER = E.SETID + '_' +   E.DEPTID  

WHERE 
  A.PO_TYPE IN ('AGR','BO')
  AND A.PO_STATUS IN ('A','D','O')
  AND D.PO_ID = 'J010000185'
  AND D.BUSINESS_UNIT = '50000'
  AND E.EFFDT =  (SELECT MAX(A_ED.EFFDT) FROM PS_DEPT_TBL A_ED
  WHERE E.SETID = A_ED.SETID
  AND E.DEPTID = A_ED.DEPTID
  AND A_ED.EFFDT <= SUBSTRING(CONVERT(CHAR,GETDATE(),121), 1, 10))

GROUP BY A.BUSINESS_UNIT,A.PO_ID, A.PO_TYPE, A.PO_STATUS, (CONVERT(CHAR(10),A.PO_DT,121)), A.VENDOR_ID, A.BUYER_ID, D.DEPTID, E.SETID + '_' +   E.DEPTID, H.ROLEUSER_SUPR  

HAVING (SUM(F.MERCHANDISE_AMT) / SUM(D.MERCHANDISE_AMT)) > .80   

ORDER BY PO_ID

问题是由于PS_PO_LINE_DISTRIB D的联接,PS_DISTRIB_LINE G的数据每行重复两次。

PS_DISTRIB_LINE G本身包含10个针对同一PO的行,因为分布是跨多个VOUCHER_ID的。我需要从PS_DISTRIB_LINE G的所有10行中得到G.MERCHANDISE_AMT的SUM(分母),但是分子上的SUM(FROM PS_PO_LINE_DISTRIB DD.MERCHANDISE_AMT必须基于PO_ID的4行中。

这里是另一种看待方式:

SELECT *
FROM PS_PO_LINE_DISTRIB D
WHERE PO_ID = 'J010000185'
AND BUSINESS_UNIT = '50000'

得出PO_ID 'J010000185'的以下数据

BUSINESS_UNIT   PO_ID        LINE_NBR   SCHED_NBR   DST_ACCT_TYPE   QTY_PO      DISTRIB_LINE_NUM    CURRENCY_CD   MERCHANDISE_AMT
50000           J010000185   1          1           DST             0.6000      1                   USD           39240.000
50000           J010000185   1          1           DST             0.4000      2                   USD           26160.000
50000           J010000185   2          1           DST             0.5000      1                   USD           7000.000
50000           J010000185   2          1           DST             0.5000      2                   USD           7000.000

因此上述D.MERCHANDISE_AMT的总和为79,400(这应该是进入NULLIF((SUM(G.MERCHANDISE_AMT) / SUM(D.MERCHANDISE_AMT)),0) AS 'Threshold'分母的金额。

如果通过以下查询在PS_DISTRIB_LINE G中查询相同的PO_ID,则结果如下:

SELECT *
FROM PS_DISTRIB_LINE
WHERE PO_ID = 'J010000185'
AND BUSINESS_UNIT = '50000'

BUSINESS_UNIT   PO_ID         VOUCHER_ID    VOUCHER_LINE_NUM    DISTRIB_LINE_NUM    BUSINESS_UNIT_GL    MONETARY_AMOUNT
50000           J010000185    00026741      2                   1                   11000               9810.000
50000           J010000185    00026741      2                   2                   41000               6540.000
50000           J010000185    00026921      2                   1                   11000               1774.130
50000           J010000185    00026921      2                   2                   41000               1774.130
50000           J010000185    00026922      2                   1                   11000               9810.000
50000           J010000185    00026922      2                   2                   41000               6540.000
50000           J010000185    00033438      2                   1                   11000               2128.280
50000           J010000185    00033438      2                   2                   41000               2128.280
50000           J010000185    00033440      2                   1                   11000               9810.000
50000           J010000185    00033440      2                   2                   41000               6540.000

{{1}中MERCHANDISE_AMT的总和为56854.82,因此对表达式PS_DISTRIB_LINE G的计算应得出以下结果:

56845.82 / 79,400 = .7194

但是,对于相同的PO_ID,由于NULLIF((SUM(G.MERCHANDISE_AMT) / SUM(D.MERCHANDISE_AMT)),0) AS 'Threshold'包含的行多于PS_DISTRIB_LINE(在此示例中为10比4),因此PS_PO_LINE_DISTRIB上的计算出的SUM变得偏斜(高于应有的值) )

如果仅使用这两个表使用它们的公共联接查询,您会看到问题的发生,PS_PO_LINE_DISTRIB(第一列)的SUM将是错误的:

D.MERCHANDISE_AMT

我在此处发布了CREATE TABLE脚本作为其他参考: https://pastebin.com/rUbRCEj5

该如何解决?

3/26编辑:

我创建了一个CTE,在最终选择中加入了2个独立的内部查询,但是我想将'(E.SETID +'_'+ E.DEPTID)分组为'REQUESTOR',但没有分组那样。我需要修改内部查询分组依据吗?

SELECT D.MERCHANDISE_AMT, G.MERCHANDISE_AMT, D.MERCHANDISE_AMT, G.MERCHANDISE_AMT, D.BUSINESS_UNIT, G.BUSINESS_UNIT, D.PO_ID, G.PO_ID, D.LINE_NBR, G.LINE_NBR, D.DISTRIB_LINE_NUM, G.DISTRIB_LINE_NUM
FROM PS_PO_LINE_DISTRIB D
INNER JOIN PS_DISTRIB_LINE G ON  G.PO_ID = D.PO_ID AND G.BUSINESS_UNIT_PO = D.BUSINESS_UNIT AND G.LINE_NBR = D.LINE_NBR AND G.SCHED_NBR = D.SCHED_NBR AND G.PO_DIST_LINE_NUM = D.DISTRIB_LINE_NUM
WHERE D.PO_ID = 'J010000185'
AND D.BUSINESS_UNIT = '50000'

MERCHANDISE_AMT MERCHANDISE_AMT   BUSINESS_UNIT  BUSINESS_UNIT  PO_ID       PO_ID        LINE_NBR   LINE_NBR    DISTRIB_LINE_NUM    DISTRIB_LINE_NUM
39240.000       9810.000          50000          50000          J010000185  J010000185   1          1           1                   1
39240.000       9810.000          50000          50000          J010000185  J010000185   1          1           1                   1
39240.000       9810.000          50000          50000          J010000185  J010000185   1          1           1                   1
26160.000       6540.000          50000          50000          J010000185  J010000185   1          1           2                   2
26160.000       6540.000          50000          50000          J010000185  J010000185   1          1           2                   2
26160.000       6540.000          50000          50000          J010000185  J010000185   1          1           2                   2
7000.000        2128.280          50000          50000          J010000185  J010000185   2          2           1                   1
7000.000        1774.130          50000          50000          J010000185  J010000185   2          2           2                   2
7000.000        1774.130          50000          50000          J010000185  J010000185   2          2           1                   1
7000.000        2128.280          50000          50000          J010000185  J010000185   2          2           2                   2

3/27编辑:

这些是我到目前为止所做的更改,我认为问题出在select(派生)语句的最后一个块上。我注释掉了Group By,因为那里似乎并不需要它,但是我遇到了语法错误。我相信需要添加别名,但是我已经添加了这些别名,但仍然出现错误。

        WITH CTE AS

        (SELECT A.BUSINESS_UNIT, A.PO_ID,  A.PO_TYPE, A.PO_STATUS, (CONVERT(CHAR(10),A.PO_DT,121)) AS 'PO_DT', A.VENDOR_SETID, A.VENDOR_ID, A.BUYER_ID, D.DEPTID, D.LINE_NBR, D.SCHED_NBR, D.DISTRIB_LINE_NUM,       
          SUM(D.MERCHANDISE_AMT) AS 'SUM_MERCH',  E.SETID + '_' +   E.DEPTID AS 'REQUESTOR', H.ROLEUSER_SUPR
        FROM PS_PO_LINE_DISTRIB D 
        INNER JOIN  PS_PO_LINE C ON  D.BUSINESS_UNIT = C.BUSINESS_UNIT AND D.PO_ID = C.PO_ID AND C.LINE_NBR = D.LINE_NBR
        INNER JOIN PS_PO_HDR A ON A.BUSINESS_UNIT = C.BUSINESS_UNIT AND A.PO_ID = C.PO_ID
        INNER JOIN  PS_DEPT_TBL E ON  E.DEPTID = D.DEPTID AND E.SETID = D.BUSINESS_UNIT_GL 
         --LEFT OUTER JOIN PS_VOUCHER_LINE F ON F.PO_ID = D.PO_ID AND F.BUSINESS_UNIT_PO = D.BUSINESS_UNIT AND F.LINE_NBR = D.LINE_NBR AND F.SCHED_NBR = D.SCHED_NBR
        INNER JOIN PS_ROLEXLATOPR H ON H.ROLEUSER = E.SETID + '_' +   E.DEPTID     
        WHERE 
            A.PO_TYPE IN ('AGR','BO')
            AND A.PO_STATUS IN ('A','D','O')
            --AND D.MERCHANDISE_AMT <> 0.00
            --AND Threshold > .80
            AND D.PO_ID = 'J010000185'
            AND D.BUSINESS_UNIT = '50000'
            AND E.EFFDT =  (SELECT MAX(A_ED.EFFDT) FROM PS_DEPT_TBL A_ED
                WHERE E.SETID = A_ED.SETID
                  AND E.DEPTID = A_ED.DEPTID
                  AND A_ED.EFFDT <= SUBSTRING(CONVERT(CHAR,GETDATE(),121), 1, 10))
        GROUP BY A.BUSINESS_UNIT,A.PO_ID, A.PO_TYPE, A.PO_STATUS, (CONVERT(CHAR(10),A.PO_DT,121)), A.VENDOR_SETID, A.VENDOR_ID, A.BUYER_ID, D.DEPTID, E.SETID + '_' +   E.DEPTID , H.ROLEUSER_SUPR, D.LINE_NBR, D.SCHED_NBR, D.DISTRIB_LINE_NUM  )
        --HAVING (SUM(F.MERCHANDISE_AMT) / SUM(D.MERCHANDISE_AMT)) > .80      --, F.MERCHANDISE_AMT, D.MERCHANDISE_AMT --,  C.LINE_NBR, D.QTY_PO, D.MERCHANDISE_AMT, D.DEPTID   

        , CTE2 AS (SELECT A.BUSINESS_UNIT, A.PO_ID,  A.PO_TYPE, A.PO_STATUS, (CONVERT(CHAR(10),A.PO_DT,121)) AS 'PO_DT', A.VENDOR_SETID, A.VENDOR_ID, A.BUYER_ID, G.DEPTID, H.ROLEUSER_SUPR, SUM(G.MERCHANDISE_AMT) AS 'SUM_MERCH' , G.BUSINESS_UNIT_PO, G.LINE_NBR, G.SCHED_NBR, G.PO_DIST_LINE_NUM
           FROM PS_DISTRIB_LINE G
           INNER JOIN  PS_PO_LINE C ON  G.BUSINESS_UNIT = C.BUSINESS_UNIT AND G.PO_ID = C.PO_ID AND C.LINE_NBR = G.LINE_NBR
           INNER JOIN PS_PO_HDR A ON A.BUSINESS_UNIT = C.BUSINESS_UNIT AND A.PO_ID = C.PO_ID
           INNER JOIN  PS_DEPT_TBL E ON  E.DEPTID = G.DEPTID AND E.SETID = G.BUSINESS_UNIT_GL 
           INNER JOIN PS_ROLEXLATOPR H ON H.ROLEUSER = E.SETID + '_' +   E.DEPTID  
           WHERE G.BUSINESS_UNIT = '50000'
           AND G.PO_ID = 'J010000185'
           AND E.EFFDT =  (SELECT MAX(A_ED.EFFDT) FROM PS_DEPT_TBL A_ED
                WHERE E.SETID = A_ED.SETID
                  AND E.DEPTID = A_ED.DEPTID
                  AND A_ED.EFFDT <= SUBSTRING(CONVERT(CHAR,GETDATE(),121), 1, 10))
           GROUP BY A.BUSINESS_UNIT,A.PO_ID, A.PO_TYPE, A.PO_STATUS, (CONVERT(CHAR(10),A.PO_DT,121)), A.VENDOR_SETID, A.VENDOR_ID, A.BUYER_ID, G.DEPTID,  H.ROLEUSER_SUPR,G.BUSINESS_UNIT_PO, G.LINE_NBR, G.SCHED_NBR, G.PO_DIST_LINE_NUM )--E.SETID + '_' +   E.DEPTID   )

        SELECT DISTINCT D.BUSINESS_UNIT, D.PO_ID, D.PO_TYPE, D.PO_STATUS, (CONVERT(CHAR(10),D.PO_DT,121)), D.VENDOR_SETID, D.VENDOR_ID, D.BUYER_ID, D.DEPTID, D.ROLEUSER_SUPR, NULLIF((G.SUM_MERCH / D.SUM_MERCH),0) AS 'Threshold'
        FROM CTE D
        LEFT OUTER JOIN CTE2 G ON G.PO_ID = D.PO_ID AND G.BUSINESS_UNIT_PO = D.BUSINESS_UNIT AND G.LINE_NBR = D.LINE_NBR AND G.SCHED_NBR = D.SCHED_NBR AND G.PO_DIST_LINE_NUM = D.DISTRIB_LINE_NUM
        GROUP BY D.BUSINESS_UNIT, D.PO_ID, D.PO_TYPE, D.PO_STATUS, (CONVERT(CHAR(10),D.PO_DT,121)), D.VENDOR_SETID, D.VENDOR_ID, D.BUYER_ID, D.DEPTID, D.ROLEUSER_SUPR

0 个答案:

没有答案