【问题标题】:CTE Group By not grouping results correctlyCTE Group 未正确分组结果
【发布时间】:2019-03-26 18:06:21
【问题描述】:

我有以下 CTE 对字段 MERCHANDISE_AMT 进行 SUM,与以下两个查询分开,然后我将这些结果合并到最终选择中。我在内部查询和/或最终的 Select 语句中遇到 Group By 问题。我希望能够将 LINE_NBR 和 PO_DIST_LINE_NUM 组合在一起,以便我有 2 行作为最终输出。我需要选择这些列,以便在最终查询的 Join 中引用它们。

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 D.LINE_NBR = C.LINE_NBR 
                INNER JOIN PS_PO_HDR A 
                    ON C.BUSINESS_UNIT = A.BUSINESS_UNIT
                    AND C.PO_ID = A.PO_ID 
                    AND A.PO_TYPE IN ('AGR','BO')
                    AND A.PO_STATUS IN ('A','D','O')
            INNER JOIN PS_DEPT_TBL E 
                ON D.DEPTID = E.DEPTID 
                AND D.BUSINESS_UNIT_GL = E.SETID 
                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))


                INNER JOIN PS_ROLEXLATOPR H 
                    ON E.SETID + '_' +   E.DEPTID = H.ROLEUSER 
    WHERE 
            D.PO_ID = 'J010000185'
        AND D.BUSINESS_UNIT = '50000'
    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 ), 

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.SCHED_NBR, 
        G.LINE_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 G.LINE_NBR = C.LINE_NBR
                INNER JOIN PS_PO_HDR A 
                    ON C.BUSINESS_UNIT = A.BUSINESS_UNIT
                    AND C.PO_ID = A.PO_ID
            INNER JOIN PS_DEPT_TBL E 
                ON  G.DEPTID = E.DEPTID
                AND G.BUSINESS_UNIT_GL = E.SETID 
                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))
                INNER JOIN PS_ROLEXLATOPR H 
                    ON E.SETID + '_' + E.DEPTID = H.ROLEUSER
    WHERE 
            G.BUSINESS_UNIT = '50000'
        AND G.PO_ID = 'J010000185'
    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.SCHED_NBR, 
        G.PO_DIST_LINE_NUM, 
        G.LINE_NBR,  
        E.SETID + '_' + E.DEPTID, 
        G.PO_DIST_LINE_NUM, 
        G.LINE_NBR )


SELECT DISTINCT  
        D.REQUESTOR, 
        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 D.PO_ID = G.PO_ID
                AND D.BUSINESS_UNIT = G.BUSINESS_UNIT_PO 
                AND D.SCHED_NBR = G.SCHED_NBR 
                AND D.LINE_NBR = G.LINE_NBR 
                AND D.DISTRIB_LINE_NUM = G.PO_DIST_LINE_NUM 

这是当前的输出:

REQUESTOR   BUSINESS_UNIT   PO_ID       PO_TYPE  PO_STATUS  (No column name)    VENDOR_SETID    VENDOR_ID   BUYER_ID    DEPTID  ROLEUSER_SUPR   Threshold
11000_744   50000           J010000185  AGR      D          2017-05-30          SHARE           90238A      EDARPINO    744     TVORHIS         0.557487
11000_744   50000           J010000185  AGR      D          2017-05-30          SHARE           90238A      EDARPINO    744     TVORHIS         0.750000
41000_744   50000           J010000185  AGR      D          2017-05-30          SHARE           90238A      EDARPINO    744     MHOPSON         0.557487
41000_744   50000           J010000185  AGR      D          2017-05-30          SHARE           90238A      EDARPINO    744     MHOPSON         0.750000

所需的最终输出如下:

REQUESTOR   BUSINESS_UNIT   PO_ID       PO_TYPE  PO_STATUS  (No column name)    VENDOR_SETID    VENDOR_ID   BUYER_ID    DEPTID  ROLEUSER_SUPR  Threshold
11000_744   50000           J010000185  AGR      D          2017-05-30          SHARE           90238A      EDARPINO    744     TVORHIS       .7209
41000_744   50000           J010000185  AGR      D          2017-05-30          SHARE           90238A      EDARPINO    744     MHOPSON       .7094

问题是“阈值”字段计算是根据请求单独分解的,我相信是因为第一个 CTE 查询中的字段 DISTRIB_LINE_NUM (别名“CTE”)。如果我从第一个查询中删除 DISTRIB_LINE_NUM 列,我会得到 2 行的输出,但为了在最终查询中进行连接,看来我需要在第一个查询中的字段上进行选择,以便能够在最终选择查询的连接中引用它(除非有解决方法)。

我不相信有一种方法可以选择非聚合列,然后不必在 Group By 中使用它,所以我正在寻找解决方案。如果有办法将 Group By 应用于最终选择,以便通过 REQUESTOR 或修改内部查询 Group By 将四行分为两部分?

【问题讨论】:

  • 也许我遗漏了一些东西,但是...如果您实际上不想对其进行分组,为什么要将 DISTRIB_LINE_NUM 包含在 group by 中以进行最终选择? AND G.PO_DIST_LINE_NUM = D.DISTRIB_LINE_NUM

标签: sql sql-server-2014


【解决方案1】:

下面应该可以工作。这个想法是您合并您的文件,然后汇总组级别并在同一行中获取您的值,然后找到结果的阈值。注意 - 在转换后为您的 PO_DT 值创建别名。

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 DISTINCT  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 

【讨论】:

  • Oly 我在运行此命令时遇到语法错误 - Incorrect syntax near the keyword 'Group'. 看起来它在 E 和 F 之间的最后一个右括号上突出显示也是错误。
  • 我正在执行阈值计算的实际字段是 G.MERCHANDISE_AMT / D.MERCHANDISE_AMT,我认为您将它们称为 G.SUM_MERCH 和 D.SUM_MERCH...
  • Order By 是选择块docs.microsoft.com/en-us/sql/t-sql/queries/… 中的最后一条语句。更新了代码,merchant_amt 有错别字。
  • 我仍然收到语法错误Msg 156, Level 15, State 1, Line 73 Incorrect syntax near the keyword 'Group'.
  • 这是您上面的代码与存在语法错误的查询的其余部分相结合,pastebin.com/W41V3sCC
猜你喜欢
  • 2020-09-26
  • 1970-01-01
  • 2023-01-09
  • 2016-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-07
  • 1970-01-01
相关资源
最近更新 更多