2017-06-01 36 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