2017-06-01 39 views
1

在我的應用程序,我已經使用店內產品描述值如下:如何unpivot的多個列SQLSERVER

ID BILLNO CUS_NAME  DATE   TOT_BAL S1 S2 S3 S4  D1 D2 D3 D4  Q1 Q2 Q3 Q4  U1 U2 U3 U4  T1 T2  T3 T4 TOTAL CUSCODE 
------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
29 1   XXX   Apr-03-2017 1932  1 2 3 NULL AAA BBB CCC NULL 6 30 6 NULL 80 35 67 NULL 480 1050 402 0 1932 DF 
40 2   YYYY   Apr-04-2017 6454  1 2 3 NULL AAA DDD FFF NULL 30 24 50 NULL 80 96 35 NULL 2400 2304 1750 0 6454 MQ  
------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

我遷移我的應用程序,以最新的技術,讓我重新構造噸表,以避免併發症。所以我想,結果將是去適應我的新表,如下所示:

BILLNO CUS_NAME DATE   TOT_BAL SNO Pdt QTY Unit Tot CUSCODE 
    1  XXX  Apr-03-2017 1932 1 AAA 6 80 480 DF 
    1  XXX  Apr-03-2017 1932 2 BBB 30 35 1050 DF 
    1  XXX  Apr-03-2017 1932 3 CCC 6 67 402 DF 
    2  YYY  Apr-04-2017 6454 1 AAA 30 80 2400 MQ 
    2  YYY  Apr-04-2017 6454 2 DDD 24 96 2304 MQ 
    2  YYY  Apr-04-2017 6454 3 FFF 50 35 1750 MQ 

我想下面的查詢,但它給錯誤的結果:

我不想空值。我只需要有有效的數據。對於例子S4,D4,Q4是空值,所以輸出應該忽略它。

SELECT BILLNO, CUS_NAME,SNOA,SNO,PDTA,PDT 
FROM [tmpFormat] 
UNPIVOT 
(
    SNO 
    FOR SNOA IN (S1,S2,S3,S4,S5,S6,S7,S8,S9,S10,S11,S12,S13,S14,S15,S16,S17) 
) UnPIV 
UNPIVOT 
(
    PDT 
    FRO PDTA IN (D1,D2,D3,D4,D5,D6,D7,D8,D9,D10,D11,D12,D13,D14,D15,D16,D17) 
) UnPiv1; 
+1

我建議你的目標表有它自己的問題 - 你存儲的數據*應該*現在跨多行。我自己的建議是使用兩個表格 - 一個用於「標題」(共同值),另一個用於「訂單項」。除非你能證明存儲性能需要,否則停止*存儲*可計算數據(TOT_BAL)。 –

+0

@Damien_The_Unbeliever是的,我有你的建議的兩張桌子,但在這裏我只提到了詳細的表格。我只會將通用信息存儲在Header表中。請幫助我 –

回答

2

嘗試CROSS APPLY

SELECT BILLNO, CUS_NAME, UnP.SNOA, UnP.PDTA --,.. 
FROM [tmpFormat] 
CROSS APPLY 
(SELECT S1 AS SNOA, D1 as PDTA --,.. 
    UNION ALL 
    SELECT S2 AS SNOA, D2 as PDTA --,.. 
-- .. 
) UnP 
0

您可以手動UNPIVOT它:

select BILLNO, CUS_NAME, DATE, TOT_BAL, S1 as SNO, D1 as Pdt, Q1 as QTY, U1 as Unit, T1 as Tot, CUSCODE 
from [tmpFormat] 
union all 
select BILLNO, CUS_NAME, DATE, TOT_BAL, S2, D2, Q2, U2, T2, CUSCODE 
from [tmpFormat] 
uniona all 
select BILLNO, CUS_NAME, DATE, TOT_BAL, S3, D3, Q3, U3, T3, CUSCODE 
from [tmpFormat] 
0

動態查詢UnPivoting:

使用SYS.COLUMNS和東西(動態查詢)來連接|將單個列中的多個列(需要添加)分組。

實施例S1,S2,S3 ......作爲SNO

後來動態查詢與逆透視處理,以多列數據轉換成單排。 帶有ID的列PDT列下的示例D1,D2,D3 .....用於映射靜態數據。

動態查詢結果存儲在表變量中供以後處理。創建了CTE的是用來連接與靜態數據非透視數據

表變量來得到最終結果。

If OBJECT_ID('UnpivotData','u') is not null 
    Drop table UnPivotData 
    go 
    Create table UnPivotData 
    (
    Id int, 
    BILLNO int, 
    Cus_Name varchar(10), 
    [Date] date, 
    Tot_Bal Int, 
    S1 smallint, 
    S2 smallint, 
    S3 smallint, 
    S4 smallint, 
    D1 varchar(3), 
    D2 varchar(3), 
    D3 varchar(3), 
    D4 varchar(3), 
    Q1 smallint, 
    Q2 smallint, 
    Q3 smallint, 
    Q4 smallint, 
    U1 smallint, 
    U2 smallint, 
    U3 smallint, 
    U4 smallint, 
    T1 smallint, 
    T2 smallint, 
    T3 smallint, 
    T4 smallint, 
    Total int, 
    CusCode varchar(2) 
    ) 

    insert into UnPivotData 
    Select 29, 1, 'XXX', '03-04-2017', 1932, 1, 2, 3, NULL, 'AAA', 'BBB', 'CCC', NULL, 6, 30, 6, NULL, 80, 35, 67, NULL, 480, 1050, 402, 0, 1932, 'DF' 
    union 
    Select 40, 2,'YYY', '04-04-2017', 6454, 1, 2, 3, NULL, 'AAA', 'DDD', 'FFF', NULL, 30, 24, 50, NULL, 80, 96, 35, NULL, 2400, 2304, 1750, 0, 6454, 'MQ' 


    DECLARE @SNO AS NVARCHAR(MAX)='',@PDT AS NVARCHAR(MAX)='',@QTY AS NVARCHAR(MAX)='', @UNIT AS NVARCHAR(MAX)='', @TOT AS NVARCHAR(MAX)='' 

    SET @SNO = STUFF((SELECT distinct ',' + QuoteName(C.name) 
       from sys.tables T join sys.columns C on T.object_id=C.object_id and T.object_id=OBJECT_ID('UnPivotData','U') and C.Name like'S'+'[0-9]%' 
       FOR XML PATH(''), TYPE 
       ).value('.', 'NVARCHAR(MAX)'),1,1,'') 
    SET @PDT = STUFF((SELECT distinct ',' + QuoteName(C.name) 
       from sys.tables T join sys.columns C on T.object_id=C.object_id and T.object_id=OBJECT_ID('UnPivotData','U') and C.Name like'D'+'[0-9]%' 
       FOR XML PATH(''), TYPE 
       ).value('.', 'NVARCHAR(MAX)'),1,1,'') 
    SET @QTY = STUFF((SELECT distinct ',' + QuoteName(C.name) 
       from sys.tables T join sys.columns C on T.object_id=C.object_id and T.object_id=OBJECT_ID('UnPivotData','U') and C.Name like'Q'+'[0-9]%' 
       FOR XML PATH(''), TYPE 
       ).value('.', 'NVARCHAR(MAX)'),1,1,'') 
    SET @UNIT = STUFF((SELECT distinct ',' + QuoteName(C.name) 
       from sys.tables T join sys.columns C on T.object_id=C.object_id and T.object_id=OBJECT_ID('UnPivotData','U') and C.Name like'U'+'[0-9]%' 
       FOR XML PATH(''), TYPE 
       ).value('.', 'NVARCHAR(MAX)'),1,1,'') 
    SET @TOT = STUFF((SELECT distinct ',' + QuoteName(C.name) 
       from sys.tables T join sys.columns C on T.object_id=C.object_id and T.object_id=OBJECT_ID('UnPivotData','U') and C.Name like'T'+'[0-9]%' 
       FOR XML PATH(''), TYPE 
       ).value('.', 'NVARCHAR(MAX)'),1,1,'') 

    Declare @Query1 Nvarchar(MAX),@Query2 Nvarchar(MAX),@Query3 Nvarchar(MAX),@Query4 Nvarchar(MAX),@Query5 Nvarchar(MAX) 

    Set @Query1='select ID,SNO from 
     (
     Select ID,'[email protected]+' from UnPivotData 
     )L 
     unpivot 
     (
      SNo for col in('+ @SNO +') 
     ) u' 

    Set @Query2='select ID,PDT from 
     (
     Select ID,'[email protected]+' from UnPivotData 
     )L 
     unpivot 
     (
      PDT for col in('+ @PDT +') 
     ) u' 

    Set @Query3='select ID,QTY from 
     (
     Select ID,'[email protected]+' from UnPivotData 
     )L 
     unpivot 
     (
      QTY for col in('+ @QTY +') 
     ) u' 

    Set @Query4='select ID,UNIT from 
     (
     Select ID,'[email protected]+' from UnPivotData 
     )L 
     unpivot 
     (
      UNIT for col in('+ @UNIT +') 
     ) u' 

    Set @Query5='select ID, TOT from 
     (
     Select ID,'[email protected]+' from UnPivotData 
     )L 
     unpivot 
     (
     TOT for col in('+ @TOT +') 
     ) u' 


    Declare @t1 table 
    (
    id int, 
    SNO Smallint 
    ) 
    Declare @t2 table 
    (
    id int, 
    PDT Varchar(3) 
    ) 
    Declare @t3 table 
    (
    id int, 
    QTY Smallint 
    ) 
    Declare @t4 table 
    (
    id int, 
    UNIT Smallint 
    ) 
    Declare @t5 table 
    (
    id int, 
    TOT Smallint 
    ) 
    Insert into @T1 execute (@Query1) 
    Insert into @T2 execute (@Query2) 
    Insert into @T3 execute (@Query3) 
    Insert into @T4 execute (@Query4) 
    Insert into @T5 execute (@Query5) 


    ;With Cte 
    as 
    (
    Select UD.Id,BILLNO,Cus_Name,[Date],Tot_Bal,SNO,Row_Number() over(partition by T1.ID Order by T1.ID)Row_NO--,PDT,QTY,UNIT,TOT 
    ,Total,CusCode 
    from UnPivotData UD join @t1 T1 on UD.Id=T1.id 
    ) 
    , 
    Cte1 
    as 
    (
    Select Cte.*,PDT from Cte Join 
    (Select *,Row_Number() over(partition by ID Order by ID)Row_NO from @t2) T2 on Cte.ID=T2.ID and Cte.Row_NO=T2.Row_NO 
    ) 
    , 
    Cte2 
    as 
    (
    Select Cte1.*,QTY from Cte1 Join 
    (Select *,Row_Number() over(partition by ID Order by ID)Row_NO from @t3) T3 on Cte1.ID=T3.ID and Cte1.Row_NO=T3.Row_NO 
    ) 
    , 
    Cte3 
    as 
    (
    Select Cte2.*,UNIT from Cte2 Join 
    (Select *,Row_Number() over(partition by ID Order by ID)Row_NO from @t4) T4 on Cte2.ID=T4.ID and Cte2.Row_NO=T4.Row_NO 
    ) 
    , 
    Cte4 
    as 
    (
    Select Cte3.*,TOT from Cte3 Join 
    (Select *,Row_Number() over(partition by ID Order by ID)Row_NO from @t5) T5 on Cte3.ID=T5.ID and Cte3.Row_NO=T5.Row_NO 
    ) 
    Select Id,BILLNO,Cus_Name,[Date],Tot_Bal,SNO,PDT,QTY,UNIT,TOT 
    ,Cuscode 
    from Cte4