2017-07-07 44 views
2

我在ms sql(版本2012)中'擺動多列'掙扎。從行獲取值到列

我想從結構

 
Supplier Nr SupplierName Manager    Service   Type_of_Service  Planned_Turnover  Turnover   TransactionID   Month     
30    Honda  Name    CityService   varchar   100 000    95 000   009000011440114   201701 
50    Honda22  Name    CityService   varchar   200 000    195 000  0090001101144    201701 
30    Honda  Name    CityService   varchar   130 000    115 000  00900111114    201702 
50    Honda22  Name    CityService   varchar   230 000    205 000  001144     201702 

得到的值到期望的形式:

 
Supplier Nr SupplierName Manager    Service   Type_of_Service  Planned_Turnover 201701  Turnover 201701   TransactionID 201701 Planned_Turnover 201702  Turnover 201702   TransactionID 201702 
    30    Honda  Name    CityService   varchar    100 000      95000    009000011440114   130 000      115 000      00900111114   
    50    Honda22 Name    CityService   varchar    200 000      195000    0090001101144   230 000      205 000      001144 

我明白,如何基於一個柱樞轉表 - 例如按月拿到營業額列一個月......但如何讓更多的值(Planned_TurnoverTurnoverTransactionID彼此相鄰的?)

感謝

+2

Google sql server pivot。 – jarlh

+0

謝謝,我已經開始使用了:) – DRastislav

+0

請解釋你爲什麼需要這個?通常這種轉換應該在客戶端處理 –

回答

2

下面是一個使用臨時表和動態SQL的例子與2個日期的樞紐。

create table #tempTable ([Supplier Nr] int, SupplierName varchar(30), Manager varchar(30), [Service] varchar(30), Type_of_Service varchar(30), Planned_Turnover varchar(30), Turnover varchar(30), TransactionID varchar(30), [Month] int); 

insert into #tempTable ([Supplier Nr],SupplierName,Manager,[Service],Type_of_Service,Planned_Turnover,Turnover,TransactionID,[Month]) values 
(30,'Honda','Name','CityService','varchar','100 000','95 000','009000011440114',201701), 
(50,'Honda22','Name','CityService','varchar','200 000','195 000','0090001101144',201701), 
(30,'Honda','Name','CityService','varchar','130 000','115 000','00900111114',201702), 
(50,'Honda22','Name','CityService','varchar','230 000','205 000','001144',201702); 

DECLARE @SQLString varchar(max); 

SET @SQLString = 'select * 
from (
    select [Supplier Nr], SupplierName, Manager, [Service], Type_of_Service, concat(''Planned_Turnover '',[Month]) as Title, Planned_Turnover as Value 
    from #tempTable where [Month] in (@Date1, @Date2) 
    union all 
    select [Supplier Nr], SupplierName, Manager, [Service], Type_of_Service, concat(''Turnover '',[Month]) as Title, Turnover as Value 
    from #tempTable where [Month] in (@Date1, @Date2) 
    union all 
    select [Supplier Nr], SupplierName, Manager, [Service], Type_of_Service, concat(''TransactionID '',[Month]) as Title, TransactionID as Value 
    from #tempTable where [Month] in (@Date1, @Date2) 
) q 
PIVOT (MAX(Value) FOR Title IN 
([Planned_Turnover @Date1],[Turnover @Date1],[TransactionID @Date1],[Planned_Turnover @Date2],[Turnover @Date2],[TransactionID @Date2]) 
) pvt'; 

declare @Date1 varchar(6) = '201701'; 
declare @Date2 varchar(6) = '201702'; 

SET @SQLString = replace(replace(@SQLString,'@Date1',@Date1),'@Date2',@Date2); 

exec (@SQLString); 

這限於2個月。如果是在幾個月的範圍內,那麼最好只爲pivot數據庫計算varchar,並在@SQLString中使用它。
示例代碼:

declare @Date1 varchar(6) = '201712'; 
declare @Date2 varchar(6) = '201802'; 

declare @PivotFields varchar(max); 
with cte as (
    select convert(date,concat(@Date1,'01')) as dt 
    union all 
    select dateadd(month,1,dt) from cte where dt < convert(date,concat(@Date2,'01')) 
) 
select @PivotFields = concat(@PivotFields+', ',quotename(word+' '+FORMAT(dt,'yyyyMM'))) 
from cte cross join (values (1,'Planned_Turnover'),(2,'Turnover'),(3,'TransactionID')) words(wordid, word) 
order by dt, wordid; 

-- result: @PivotFields="[Planned_Turnover 201712], [Turnover 201712], [TransactionID 201712], [Planned_Turnover 201801], [Turnover 201801], [TransactionID 201801], [Planned_Turnover 201802], [Turnover 201802], [TransactionID 201802]" 
+0

如果你喜歡動態sql,最好使用參數化的'sp_executesql'而不是'exec' –

+0

@MikhailLobanov我知道它更安全,但這些日期可能不是用戶輸入,因此代碼注入varchar(6)沒有危險。我試過了,但是這種方法不能代替PIVOT字段中的變量。所以,因爲無論如何都需要替換,使用參數會傷害我的高爾夫球編碼器本能。 – LukStorms