基于ID的转置数据/动态枢轴(无需计算)

时间:2018-10-30 11:34:18

标签: sql sql-server tsql pivot transpose

我需要一些帮助来根据数字列转换数据。 ID是动态的(可以高达35)。

格式:

ID  SKU Q       A
1   123 Q1      A1
2   123 Q100    A2
3   123 Q200    A3
1   456 Q2      A1
2   456 Q200    A4
3   456 Q201    A5
4   456 Q203    A6
1   789 Q1      A7
2   789 Q2      A2
3   789 Q3      A3

需要按照以下条件进行换位:

SKU  Q+A (ID1)      Q+A (ID2)   Q+A (ID3)       Q+A (ID4)
123  Q1:A1          Q100:A2     Q200A3          NULL
456  Q100:A2        Q200:A4     Q201:A5         Q203:A6
789  Q1:A7          Q2:A2       Q3:A3           NULL

你们能帮忙吗?

谢谢。

2 个答案:

答案 0 :(得分:1)

以下是使用CASE作为枢轴的解决方案:

declare @t table (ID int,SKU int,Q varchar(100),A varchar(100))

insert into @t
values
    (   1   ,   123 ,   'Q1'    ,   'A1'    )
,   (   2   ,   123 ,   'Q100'  ,   'A2'    )
,   (   3   ,   123 ,   'Q200'  ,   'A3'    )
,   (   1   ,   456 ,   'Q2'    ,   'A1'    )
,   (   2   ,   456 ,   'Q200'  ,   'A4'    )
,   (   3   ,   456 ,   'Q201'  ,   'A5'    )
,   (   4   ,   456 ,   'Q203'  ,   'A6'    )
,   (   1   ,   789 ,   'Q1'    ,   'A7'    )
,   (   2   ,   789 ,   'Q2'    ,   'A2'    )
,   (   3   ,   789 ,   'Q3'    ,   'A3'    )


;with setup as 
(
select distinct SKU
    ,Q+':'+A [Q+A]
    ,'Q+A (ID'+cast(ID as varchar(2)) + ')' PivotOn
from @t
)

select SKU
    , max(case when PivotOn = 'Q+A (ID1)' then [Q+A] end) as [Q+A (ID1)]
    , max(case when PivotOn = 'Q+A (ID2)' then [Q+A] end) as [Q+A (ID2)]
    , max(case when PivotOn = 'Q+A (ID3)' then [Q+A] end) as [Q+A (ID3)]
    , max(case when PivotOn = 'Q+A (ID4)' then [Q+A] end) as [Q+A (ID4)]

from setup
group by SKU

结果:

SKU Q+A (ID1)   Q+A (ID2)   Q+A (ID3)   Q+A (ID4)
123 Q1:A1       Q100:A2     Q200:A3     NULL
456 Q2:A1       Q200:A4     Q201:A5     Q203:A6
789 Q1:A7       Q2:A2       Q3:A3       NULL

您需要将案例声明的值取为最大ID(在您指定的案例中为35)。

答案 1 :(得分:1)

样本数据

IF OBJECT_ID('tempdb..#TempData')IS NOT NULL
DROP TABLE #TempData

DECLARE @t table (ID int,SKU int,Q varchar(100),A varchar(100))
Insert into @t
values
    (   1   ,   123 ,   'Q1'    ,   'A1'   )
,   (   2   ,   123 ,   'Q100'  ,   'A2'   )
,   (   3   ,   123 ,   'Q200'  ,   'A3'   )
,   (   1   ,   456 ,   'Q2'    ,   'A1'   )
,   (   2   ,   456 ,   'Q200'  ,   'A4'   )
,   (   3   ,   456 ,   'Q201'  ,   'A5'   )
,   (   4   ,   456 ,   'Q203'  ,   'A6'   )
,   (   1   ,   789 ,   'Q1'    ,   'A7'   )
,   (   2   ,   789 ,   'Q2'    ,   'A2'   )
,   (   3   ,   789 ,   'Q3'    ,   'A3'   )
,   (   1   ,   478 ,   'Q10'    ,  'A47'  )
,   (   2   ,   478 ,   'Q20'    ,  'A12'  )
,   (   3   ,   478 ,   'Q34'    ,  'A03'  )
,   (   4   ,   478 ,   'Q34'    ,  'A03'  )
,   (   5   ,   478 ,   'Q34'    ,  'A03'  )
,   (   6   ,   478 ,   'Q34'    ,  'A03'  )
,   (   7   ,   478 ,   'Q34'    ,  'A03'  )
,   (   8   ,   478 ,   'Q34'    ,  'A03'  )


SELECT *,(Q+':'+A) AS Qdata, 'Q+A('+CAST(DENSE_RANK()OVER(ORDER BY ID) AS VARCHAR(10))+')'AS RID
INTO #TempData
FROM @t

使用Pivot的动态Sql

DECLARE @Columns VARCHAR(MAX) ='',
        @Columns2 VARCHAR(MAX) ='',
        @Sql nvarchar (max)=''

SELECT @Columns=STUFF((SELECT DISTINCT ',',+ QUOTENAME(RID )
                FROM  #TempData FOR XML PATH ('')),1,1,'')
SELECT @Columns2=STUFF((SELECT DISTINCT ',',+ 'ISNULL(MAX('+QUOTENAME(RID ) +') ,''NA'') AS '+QUOTENAME(RID )
                FROM  #TempData FOR XML PATH ('')),1,1,'')

SET @Sql='SELECT SKU,'+@Columns2+' FROM
(
SELECT * FROM #TempData
) AS SRC
PIVOT
(
MAX(Qdata) FOR RID IN('+@Columns+') 
) AS PVT 
GROUP BY SKU'
PRINT @Sql
EXEC (@Sql)

结果

SKU     Q+A(1)      Q+A(2)      Q+A(3)      Q+A(4)      Q+A(5)      Q+A(6)      Q+A(7)      Q+A(8)
--------------------------------------------------------------------------------------------------
123     Q1:A1       Q100:A2     Q200:A3      NA           NA         NA           NA        NA
456     Q2:A1       Q200:A4     Q201:A5     Q203:A6       NA         NA           NA        NA
478     Q10:A47     Q20:A12     Q34:A03     Q34:A03     Q34:A03     Q34:A03     Q34:A03     Q34:A03
789     Q1:A7       Q2:A2       Q3:A3        NA           NA         NA           NA        NA