Агрегирование полей неправильно суммируется на основе объединения с другой таблицей - PullRequest
0 голосов
/ 26 марта 2019

У меня есть запрос ниже, где я пытаюсь рассчитать процент на основе суммы G.MERCHANDISE_AMT, деленной на сумму D.MERCHANDISE_AMT. PO_ID в этой таблице содержит 2 номера строк, а каждый номер строки имеет 2 распределения, всего 4 строки, и я получаю СУММУ D.MERCHANDISE_AMT по всем 4 строкам. Обратите внимание, что G.MERCHANDISE_AMT - это поле в этих двух таблицах, PS_PO_LINE_DISTRIB D и PS_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 строк для одного и того же заказа, потому что распределение происходит по нескольким идентификаторам VOUCHER_ID. От PS_DISTRIB_LINE G мне нужно получить СУММУ G.MERCHANDISE_AMT из всех 10 строк (знаменатель), однако СУММА в числителе (ОТ PS_PO_LINE_DISTRIB D) D.MERCHANDISE_AMT должна основываться на 4 строках для этого PO_ID.

Вот еще один способ взглянуть на это:

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'.

Если я запрашиваю этот же PO_ID в PS_DISTRIB_LINE G с помощью следующего запроса, это результаты:

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

Сумма MERCHANDISE_AMT от PS_DISTRIB_LINE G равна 56854,82, поэтому вычисление по выражению NULLIF((SUM(G.MERCHANDISE_AMT) / SUM(D.MERCHANDISE_AMT)),0) AS 'Threshold' должно привести к следующему:

56845,82 / 79,400 = .7194

Однако, поскольку PS_DISTRIB_LINE содержит больше строк, чем PS_PO_LINE_DISTRIB (10 против 4 в этом примере) для того же PO_ID, вычисленная сумма на PS_PO_LINE_DISTRIB становится искаженной (выше, чем должна быть)

Если я опрошу только эти две таблицы, используя их общие объединения, вы увидите, что проблема возникает, и SUM из D.MERCHANDISE_AMT (1-й столбец) будет неправильным:

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

Я разместил здесь скрипты CREATE TABLE в качестве дополнительной ссылки: https://pastebin.com/rUbRCEj5

Что можно сделать, чтобы преодолеть это?

3/26 РЕДАКТИРОВАТЬ:

Я создал CTE с двумя отдельными внутренними запросами, которые были объединены в конечном выборе, однако я хочу сгруппировать по `(E.SETID + '_' + E.DEPTID) AS 'REQUESTOR', но это не группировка сюда. Нужно ли изменять внутренние запросы 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

3/27 РЕДАКТИРОВАТЬ:

Это изменения, которые я сделал до сих пор, и я думаю, что проблема возникает в последнем блоке операторов выбора (производных). Я прокомментировал 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 'PO_SUM_MERCH_AMT',  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_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_SETID, A.VENDOR_ID, A.BUYER_ID, D.DEPTID, E.SETID + '_' +   E.DEPTID , H.ROLEUSER_SUPR      )


    , 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_AMT', G.BUSINESS_UNIT_PO --, G.SCHED_NBR, G.LINE_NBR, G.PO_DIST_LINE_NUM, G.VOUCHER_ID, G.VOUCHER_LINE_NUM, G.DISTRIB_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,
        G.BUSINESS_UNIT_PO, H.ROLEUSER_SUPR )

    Select REQUESTOR, BUSINESS_UNIT, PO_ID, PO_TYPE, PO_STATUS, PO_DT, VENDOR_SETID, VENDOR_ID, BUYER_ID, DEPTID, ROLEUSER_SUPR, NULLIF((SUM_MERCHA / SUM_MERCHB),0) AS 'Threshold' from
    (
    Select REQUESTOR, BUSINESS_UNIT, PO_ID, PO_TYPE, PO_STATUS, PO_DT, VENDOR_SETID, VENDOR_ID, BUYER_ID, DEPTID, ROLEUSER_SUPR, SUM(SUM_MERCHA) as SUM_MERCHA, SUM(SUM_MERCHB) as SUM_MERCHB from (
    SELECT  D.REQUESTOR, D.BUSINESS_UNIT, D.PO_ID, D.PO_TYPE, D.PO_STATUS, (CONVERT(CHAR(10),D.PO_DT,121)) as PO_DT, D.VENDOR_SETID, D.VENDOR_ID, D.BUYER_ID, D.DEPTID, D.ROLEUSER_SUPR, G.MERCHANDISE_AMT as SUM_MERCHA,  D.MERCHANDISE_AMT as SUM_MERCHB
    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.SCHED_NBR = D.SCHED_NBR AND G.LINE_NBR = D.LINE_NBR AND G.PO_DIST_LINE_NUM = D.DISTRIB_LINE_NUM)
    --Group by D.REQUESTOR, D.BUSINESS_UNIT, D.PO_ID, D.PO_TYPE, D.PO_STATUS, PO_DT, D.VENDOR_SETID, D.VENDOR_ID, D.BUYER_ID, D.DEPTID, D.ROLEUSER_SUPR) E ) F 
...