Sql-Server

長數據動態轉換為多列寬數據

  • December 11, 2017

我正在嘗試轉換長數據:

ID|SchoolID|Section|RepScore|SportsScore|PartyScore  
1 |20      |1      |23.2    |70.2       |42.3          
2 |20      |6      |65.2    |75.8       |52.3        
3 |20      |7      |77.2    |72.2       |66.3       
4 |21      |10     |13.2    |40.2       |72.3         
5 |21      |11     |25.2    |55.8       |72.3         
6 |21      |12     |37.2    |62.2       |76.3       

到寬數據(我只使用前三行來保持簡短):

SchoolID|RpScr1|RpScr6|RpScr7|SprtScr1|SprtScr6|SprtScr7|Prty1|Prty6|Prty7  
20      |23.2  |65.2  |77.2  |70.2    |75.8    |72.2    |42.3 |52.3 |66.3 

我試過這個:

DECLARE @cols VARCHAR(1000)
DECLARE @cols2 VARCHAR(1000)
DECLARE @cols3 VARCHAR(1000)
DECLARE @sqlquery VARCHAR(2000)
SELECT  @cols = STUFF(( SELECT distinct  '], [a' + cast([Section] as varchar)
                       FROM [dbo].[SchoolData] FOR XML PATH('') ), 1, 2, '') + ']'
SELECT  @cols2 = STUFF(( SELECT distinct  '], [b' + cast([Section] as varchar)
                       FROM [dbo].[SchoolData] FOR XML PATH('') ), 1, 2, '') + ']'
SELECT  @cols3 = STUFF(( SELECT distinct  '], [c' + cast([Section] as varchar)
                       FROM [dbo].[SchoolData] FOR XML PATH('') ), 1, 2, '') + ']'
SET @sqlquery = 'SELECT * FROM
     (SELECT z.Section,z.RepScore,z.SportsScore,z.PartyScore
      FROM [dbo].[SchoolData] z) base
      PIVOT (Max(RepScore) FOR [Section] IN (' + @cols + ')) AS finalpivot
      PIVOT (Max(SportsScore) FOR [Section] IN (' + @cols + ')) AS finalpivot2
      PIVOT (Max(PartyScore) FOR [Section] IN (' + @cols + ')) AS finalpivot3'


EXECUTE ( @sqlquery )

這是我得到的錯誤:Msg 8114, Level 16, State 1, Line 7 將數據類型 nvarchar 轉換為 int 時出錯。消息 473,級別 16,狀態 1,第 7 行 PIVOT 運算符中提供了不正確的值“a9”。消息 207,級別 16,狀態 1,第 8 行 列名“部分”無效。

當我嘗試這樣的一個時:

DECLARE @cols VARCHAR(1000)  
DECLARE @sqlquery VARCHAR(2000)  
   SELECT  @cols = STUFF(( SELECT distinct  '], [a' + cast([Section] as varchar)  
                           FROM [dbo].[SchoolData] FOR XML PATH('') ), 1, 2, '') + ']'    
SET @sqlquery = 'SELECT * FROM  
         (SELECT z.Section,z.RepScore,z.SportsScore,z.PartyScore  
          FROM [dbo].[SchoolData] z) base  
          PIVOT (Max(RepScore) FOR [Section] IN (' + @cols + ')) AS   finalpivot' 

它只適用於一列並給出這樣的列名

$$ 1 $$,$$ 6 $$,$$ 7 $$. 但它不適用於我需要的多個列。有任何想法嗎?

你在找這個嗎

CREATE TABLE #T(ID INT,SchoolID INT,Section INT,RepScore DECIMAL(5,2)
,SportsScore DECIMAL(5,2),PartyScore DECIMAL(5,2))
INSERT INTO #T VALUES
(1,20,1 ,23.2,70.2,42.3)         
,(2,20,6 ,65.2,75.8,52.3)       
,(3,20,7 ,77.2,72.2,66.3)      
,(4,21,10,13.2,40.2,72.3)        
,(5,21,11,25.2,55.8,72.3)        
,(6,21,12,37.2,62.2,76.3) 
--SELECT * FROM #T

DECLARE @colRpName VARCHAR(1000)
DECLARE @colRpVal VARCHAR(1000)
DECLARE @colSportVal VARCHAR(1000)
DECLARE @colPartyVal VARCHAR(1000)
DECLARE @sqlquery VARCHAR(2000)

SELECT  
@colRpName = STUFF(( SELECT distinct  '], [' + cast([Section] as varchar)
                       FROM #T t1  FOR XML PATH('') ), 1, 2, '') + ']'
,  @colRpVal = STUFF(( SELECT distinct  ', [' + cast([Section] as varchar) +'] as '+'[a ' + cast([Section] as varchar)+']'
                       FROM #T t1  FOR XML PATH('') ), 1, 2, '') + ''
,  @colSportVal = STUFF(( SELECT distinct  ', [' + cast([Section] as varchar) +'] as '+'[b ' + cast([Section] as varchar)+']'
                       FROM #T t1  FOR XML PATH('') ), 1, 2, '') + ''
,  @colPartyVal = STUFF(( SELECT distinct  ', [' + cast([Section] as varchar) +'] as '+'[c ' + cast([Section] as varchar)+']'
                       FROM #T t1 FOR XML PATH('') ), 1, 2, '') + ''
from #T t

--SELECT @colRpName,@colRpVal

SET @sqlquery = '
SELECT fp.SchoolID,'+@colRpVal+'
,'+@colSportVal+'
,'+@colPartyVal+'
FROM  
(SELECT SchoolID,[section],RepScore

FROM #T z) base  
PIVOT (sum(RepScore) FOR [section] IN ('+@colRpName+')) AS   fp
CROSS APPLY 
(
SELECT fp1.SchoolID,'+@colSportVal+'
FROM  
(SELECT SchoolID,[section],SportsScore

FROM #T z) base1  
PIVOT (sum(SportsScore) FOR [section] IN ('+@colRpName+')) AS   fp1
WHERE fp1.SchoolID=fp.SchoolID
)ca
CROSS APPLY 
(
SELECT fp2.SchoolID,'+@colPartyVal+'
FROM  
(SELECT SchoolID,[section],PartyScore

FROM #T z) base2
PIVOT (sum(PartyScore) FOR [section] IN ('+@colRpName+')) AS   fp2
WHERE fp2.SchoolID=fp.SchoolID
)ca1
 ' 

--print @sqlquery
 EXEC(@sqlquery)-- please use sp_executesql

DROP TABLE #T

如果您已經知道 Section + score 類型的所有可能值,您可以嘗試以下樞軸/反樞軸技巧:

create table my_table(ID int, SchoolID int, Section int, RepScore decimal(8, 2), SportsScore decimal(8, 2), PartyScore decimal(8, 2))
insert into my_table
values(  1, 20, 1 , 23.2, 70.2, 42.3),      
       (2, 20, 6 , 65.2, 75.8, 52.3),    
       (3, 20, 7 , 77.2, 72.2, 66.3),   
       (4, 21, 10, 13.2, 40.2, 72.3),     
       (5, 21, 11, 25.2, 55.8, 72.3),     
       (6, 21, 12, 37.2, 62.2, 76.3)     
       (1, 20, 1 , 23.2, 70.2, 42.3),      
       (2, 20, 6 , 65.2, 75.8, 52.3),    
       (3, 20, 7 , 77.2, 72.2, 66.3),   
       (4, 21, 10, 13.2, 40.2, 72.3),     
       (5, 21, 11, 25.2, 55.8, 72.3),     
       (6, 21, 12, 37.2, 62.2, 76.3)  




select  SchoolID, 
       [RepScore1],
       [SportsScore1],
       [PartyScore1],
       [RepScore6],
       [SportsScore6],
       [PartyScore6],
       [RepScore7],
       [SportsScore7],
       [PartyScore7],
       [RepScore10],
       [SportsScore10],
       [PartyScore10],
       [RepScore11],
       [SportsScore11],
       [PartyScore11],
       [RepScore12],
       [SportsScore12]
from (
   select SchoolID, score, col+cast(Section as varchar) as col
   from my_table t
   unpivot(score for col in (RepScore, SportsScore, PartyScore)) up
   ) t
pivot(max(score) for col in([RepScore1],
                           [SportsScore1],
                           [PartyScore1],
                           [RepScore6],
                           [SportsScore6],
                           [PartyScore6],
                           [RepScore7],
                           [SportsScore7],
                           [PartyScore7],
                           [RepScore10],
                           [SportsScore10],
                           [PartyScore10],
                           [RepScore11],
                           [SportsScore11],
                           [PartyScore11],
                           [RepScore12],
                           [SportsScore12])) p

引用自:https://dba.stackexchange.com/questions/192532