【问题标题】:Transform column into additional row将列转换为附加行
【发布时间】:2021-07-15 21:54:34
【问题描述】:

我有以下查询(为简单起见删除了其他列),我有两列,MERCHANDISE_AMTFREIGHT_AMT。我想在MERCHANDISE_AMT 列中输出带有 FREIGHT_AMT 值的附加行,而不是单独的列。我想知道是否有办法在不使用 UNION 运算符的情况下做到这一点?所有其他列将包含与第一行相同的值,除了 VOUCHER_LINE_NBR 它将是下一个增量数字(即 2)它仅适用于填充“FREIGHT_AMT”而不需要额外行输出的情况'MERCHANDISE_AMT' 列中的值('FREIGHT_AMT')。

SELECT CONCAT(A.BUSINESS_UNIT,A.VOUCHER_ID) AS INVOICE_ID, A.VOUCHER_LINE_NUM, 
CASE WHEN EXISTS (SELECT 1 FROM PS_DISTRIB_LINE 
                  WHERE BUSINESS_UNIT = A.BUSINESS_UNIT
                    AND VOUCHER_ID = A.VOUCHER_ID
                    AND VOUCHER_LINE_NUM = A.VOUCHER_LINE_NUM)                                                                             
          THEN 'ITEM' ELSE 'MISCELLANEOUS' END, A.MERCHANDISE_AMT, A.FREIGHT_AMT


FROM FROM PS_VOUCHER_LINE A
LEFT OUTER JOIN PS_DISTRIB_LINE B ON B.BUSINESS_UNIT = A.BUSINESS_UNIT AND B.VOUCHER_ID = A.VOUCHER_ID AND B.VOUCHER_LINE_NUM = A.VOUCHER_LINE_NUM
LEFT OUTER JOIN PS_VOUCHER C ON C.BUSINESS_UNIT = A.BUSINESS_UNIT AND C.VOUCHER_ID = A.VOUCHER_ID
LEFT OUTER JOIN PS_VCHR_LINE_WTHD D ON D.BUSINESS_UNIT = A.BUSINESS_UNIT AND D.VOUCHER_ID = A.VOUCHER_ID AND D.VOUCHER_LINE_NUM = A.VOUCHER_LINE_NUM AND D.WTHD_ENTITY = 'IRS'
LEFT OUTER JOIN PS_VCHR_LINE_WTHD DD ON DD.BUSINESS_UNIT = D.BUSINESS_UNIT AND DD.VOUCHER_ID = D.VOUCHER_ID AND DD.VOUCHER_LINE_NUM = D.VOUCHER_LINE_NUM AND DD.WTHD_ENTITY = 'PA'
LEFT OUTER JOIN PS_VENDOR E ON E.BUSINESS_UNIT = B.BUSINESS_UNIT_GL AND E.VENDOR_ID = A.VENDOR_ID
LEFT OUTER JOIN #CloudXWalk F ON F.BUSINESS_UNIT = B.BUSINESS_UNIT_GL AND (F.DEPTID = 'All' OR F.DEPTID = B.DEPTID)
LEFT OUTER JOIN #CloudCostCenter H ON H.BUSINESS_UNIT = B.BUSINESS_UNIT_GL AND H.DEPTID = B.DEPTID
LEFT OUTER JOIN #CloudProjectCodes G ON G.PS_PROJECT_CODE = B.PROJECT_ID
LEFT OUTER JOIN PS_PYMNT_VCHR_XREF I ON I.BUSINESS_UNIT = A.BUSINESS_UNIT AND I.VOUCHER_ID = A.VOUCHER_ID

WHERE 
C.INVOICE_DT > '01-03-2019'
AND C.ACCOUNTING_DT < '06-01-2021'
--AND A.BUSINESS_UNIT = '90059'
AND I.PYMNT_ID = ''
AND C.CLOSE_STATUS <> 'C'

现有示例输出:

INVOICE_ID      VOUCHER_LINE_NUM    (No column name)    MERCHANDISE_AMT    FREIGHT_AMT
1100000720667   1                    ITEM               17480.820          58.24000  

所需的样本输出:

INVOICE_ID      VOUCHER_LINE_NUM    (No column name)    MERCHANDISE_AMT    
1100000720667   1                    ITEM               17480.820
1100000720667   2                    ITEM               58.24000

【问题讨论】:

    标签: sql sql-server-2014


    【解决方案1】:

    所以您想将FREIGHT_AMT 别名为MERCHANDISE_AMT 并将其显示在单独的行上?

    你可以使用UNION:

    ;
    with cte (
        INVOICE_ID
      , VOUCHER_LINE_NUM
      , [(No column name)]
      , MERCHANDISE_AMT
      , FREIGHT_AMT
    ) as (
      SELECT CONCAT(A.BUSINESS_UNIT,A.VOUCHER_ID) AS INVOICE_ID
      , A.VOUCHER_LINE_NUM
      , CASE 
          WHEN EXISTS (
              SELECT 1 
              FROM PS_DISTRIB_LINE 
              WHERE BUSINESS_UNIT = A.BUSINESS_UNIT
                AND VOUCHER_ID = A.VOUCHER_ID
                AND VOUCHER_LINE_NUM = A.VOUCHER_LINE_NUM
            )
            THEN 'ITEM'
          ELSE 'MISCELLANEOUS'
        END
      , A.MERCHANDISE_AMT
      , A.FREIGHT_AMT
    
      FROM FROM PS_VOUCHER_LINE A
        LEFT OUTER JOIN PS_DISTRIB_LINE B ON B.BUSINESS_UNIT = A.BUSINESS_UNIT AND B.VOUCHER_ID = A.VOUCHER_ID AND B.VOUCHER_LINE_NUM = A.VOUCHER_LINE_NUM
        LEFT OUTER JOIN PS_VOUCHER C ON C.BUSINESS_UNIT = A.BUSINESS_UNIT AND C.VOUCHER_ID = A.VOUCHER_ID
        LEFT OUTER JOIN PS_VCHR_LINE_WTHD D ON D.BUSINESS_UNIT = A.BUSINESS_UNIT AND D.VOUCHER_ID = A.VOUCHER_ID AND D.VOUCHER_LINE_NUM = A.VOUCHER_LINE_NUM AND D.WTHD_ENTITY = 'IRS'
        LEFT OUTER JOIN PS_VCHR_LINE_WTHD DD ON DD.BUSINESS_UNIT = D.BUSINESS_UNIT AND DD.VOUCHER_ID = D.VOUCHER_ID AND DD.VOUCHER_LINE_NUM = D.VOUCHER_LINE_NUM AND DD.WTHD_ENTITY = 'PA'
        LEFT OUTER JOIN PS_VENDOR E ON E.BUSINESS_UNIT = B.BUSINESS_UNIT_GL AND E.VENDOR_ID = A.VENDOR_ID
        LEFT OUTER JOIN #CloudXWalk F ON F.BUSINESS_UNIT = B.BUSINESS_UNIT_GL AND (F.DEPTID = 'All' OR F.DEPTID = B.DEPTID)
        LEFT OUTER JOIN #CloudCostCenter H ON H.BUSINESS_UNIT = B.BUSINESS_UNIT_GL AND H.DEPTID = B.DEPTID
        LEFT OUTER JOIN #CloudProjectCodes G ON G.PS_PROJECT_CODE = B.PROJECT_ID
        LEFT OUTER JOIN PS_PYMNT_VCHR_XREF I ON I.BUSINESS_UNIT = A.BUSINESS_UNIT AND I.VOUCHER_ID = A.VOUCHER_ID
    
      WHERE C.INVOICE_DT > '01-03-2019'
        AND C.ACCOUNTING_DT < '06-01-2021'
        --AND A.BUSINESS_UNIT = '90059'
        AND I.PYMNT_ID = ''
        AND C.CLOSE_STATUS <> 'C'
    )
    
    SELECT INVOICE_ID
    , VOUCHER_LINE_NUM
    , [(No column name)]
    , MERCHANDISE_AMT
    FROM cte
    
    UNION
    SELECT INVOICE_ID
    , VOUCHER_LINE_NUM
    , [(No column name)]
    , FREIGHT_AMT AS MERCHANDISE_AMT
    FROM cte
    

    【讨论】:

    • 我对使用 UNION 的担忧是,我的查询中实际上有超过 100 列(出于简单原因,我从上面删除了),因此必须重复其中的每一列可能有点不切实际工会。我可以使用CROSS APPLY 来消除复制每一列的需要吗?
    【解决方案2】:

    您可以使用unpivot 从列到新行

    ;WITH CTE AS (
    SELECT CONCAT(A.BUSINESS_UNIT,A.VOUCHER_ID) AS INVOICE_ID, A.VOUCHER_LINE_NUM, 
    CASE WHEN EXISTS (SELECT 1 FROM PS_DISTRIB_LINE 
                      WHERE BUSINESS_UNIT = A.BUSINESS_UNIT
                        AND VOUCHER_ID = A.VOUCHER_ID
                        AND VOUCHER_LINE_NUM = A.VOUCHER_LINE_NUM)                                                                             
              THEN 'ITEM' ELSE 'MISCELLANEOUS' END AS UnNamedColumn, A.MERCHANDISE_AMT, A.FREIGHT_AMT
    
    
    FROM FROM PS_VOUCHER_LINE A
    LEFT OUTER JOIN PS_DISTRIB_LINE B ON B.BUSINESS_UNIT = A.BUSINESS_UNIT AND B.VOUCHER_ID = A.VOUCHER_ID AND B.VOUCHER_LINE_NUM = A.VOUCHER_LINE_NUM
    LEFT OUTER JOIN PS_VOUCHER C ON C.BUSINESS_UNIT = A.BUSINESS_UNIT AND C.VOUCHER_ID = A.VOUCHER_ID
    LEFT OUTER JOIN PS_VCHR_LINE_WTHD D ON D.BUSINESS_UNIT = A.BUSINESS_UNIT AND D.VOUCHER_ID = A.VOUCHER_ID AND D.VOUCHER_LINE_NUM = A.VOUCHER_LINE_NUM AND D.WTHD_ENTITY = 'IRS'
    LEFT OUTER JOIN PS_VCHR_LINE_WTHD DD ON DD.BUSINESS_UNIT = D.BUSINESS_UNIT AND DD.VOUCHER_ID = D.VOUCHER_ID AND DD.VOUCHER_LINE_NUM = D.VOUCHER_LINE_NUM AND DD.WTHD_ENTITY = 'PA'
    LEFT OUTER JOIN PS_VENDOR E ON E.BUSINESS_UNIT = B.BUSINESS_UNIT_GL AND E.VENDOR_ID = A.VENDOR_ID
    LEFT OUTER JOIN #CloudXWalk F ON F.BUSINESS_UNIT = B.BUSINESS_UNIT_GL AND (F.DEPTID = 'All' OR F.DEPTID = B.DEPTID)
    LEFT OUTER JOIN #CloudCostCenter H ON H.BUSINESS_UNIT = B.BUSINESS_UNIT_GL AND H.DEPTID = B.DEPTID
    LEFT OUTER JOIN #CloudProjectCodes G ON G.PS_PROJECT_CODE = B.PROJECT_ID
    LEFT OUTER JOIN PS_PYMNT_VCHR_XREF I ON I.BUSINESS_UNIT = A.BUSINESS_UNIT AND I.VOUCHER_ID = A.VOUCHER_ID
    
    WHERE 
    C.INVOICE_DT > '01-03-2019'
    AND C.ACCOUNTING_DT < '06-01-2021'
    --AND A.BUSINESS_UNIT = '90059'
    AND I.PYMNT_ID = ''
    AND C.CLOSE_STATUS <> 'C'
    )
    
    SELECT INVOICE_ID,VOUCHER_LINE_NUM - 1 + row_number() over (partition by INVOICE_ID order by (select NULL)) AS VOUCHER_LINE_NUM,UnNamedColumn
    FROM CTE
    unpivot (value FOR col IN (MERCHANDISE_AMT, FREIGHT_AMT)) u
    

    【讨论】:

    • 使用这种方法我不需要输出 FREIGHT_AMT 列是否正确? FREIGHT_AMT 将在单独行的 MERCHANDISE_AMT 列下输出,正如我在上面所需的输出中所示?
    • 是的 unpivot 与枢轴相反,将列分成行。
    • 我希望 VOUCHER_LINE_NUM 从第一行开始递增(即 2)?我可能还有另一个专栏,我还需要将其转入MERCHANDISE_AMT,所以我想要这个计数器。怎么可能做到?
    • 可以在 select 子句中使用 (VOUCHER_LINE_NUM + 1) AS VOUCHER_LINE_NUM 或使用 row_number 窗口函数
    • hmmm 当我在最终选择中使用 (VOUCHER_LINE_NUM + 1) 时,每行的值都为 2。我应该从 1 开始,并在随后的每一行增加 1,即 1、2、3、4 等...
    猜你喜欢
    • 1970-01-01
    • 2020-04-05
    • 2016-05-10
    • 2015-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-26
    • 2020-09-23
    相关资源
    最近更新 更多