SQL一行多列的行轉列處理


表結構如圖,四個列分別是日期、路名、目的地、運量。每天,每條路的目的地數量不固定

fEventDay

fRoadName

fDestination

fFreight

20151128

蘇嘉杭

常州

163

20151128

蘇嘉杭

無錫

441

20151128

蘇嘉杭

蘇州

441

20151128

蘇嘉杭

南通

441

要求輸出這樣的報表,以日期、道路、運量倒序排列。實際報表里的目的地有很多,這里只截取前面的幾列

 

EventDay

RoadName

Destination1

Freight1

Destination10

Freight10

Destination2

Freight2

20150304

繞城高速

南通

673

NULL

NULL

蘇州

673

20150304

蘇嘉杭

常州

533

NULL

NULL

南通

533

20150305

繞城高速

淮安

892

鹽城

244

連雲港

892

20150305

蘇嘉杭

常州

878

連雲港

255

蘇州

878

 

難點在於,目的地的數量不確定,感覺傳統的行轉列處理方法難以實現,因為分列的參數不固定,需要根據記錄動態生成。

為此,設想先生成分列參數,再拼裝SQL語句,最后輸出結果

實現的存儲過程

ALTER PROCEDURE  [dbo].[ProcedureName]
(
	@S_Day  varchar(10),--開始日期
	@E_Day  varchar(10), --日期范圍
	@RoadName  varchar(300), --道路(多值查詢)
	@Destination varchar(300), --目的地(多值查詢)
	@order  varchar(max)--排序字段(多值)
    )	 
AS
BEGIN
select fEventDay as  EventDay ,[fRoadName] as RoadName,[fDestination] as Destination
,'Destination'+convert(varchar(2), row_number() over(partition by [fEventDay],[fRoadName]  order by [fFreight] desc,[fDestination])) as TopNum
 into #GoodsDestination
FROM  [TOCC].[dbo].[tGoodsDestination]  WITH(INDEX(Index_Day)) where 1=1-- and fEventDay=20170320
group by [fEventDay],[fRoadName],[fDestination],[fFreight] 
 order by [fEventDay],[fRoadName],[fFreight] desc,[fDestination]

DECLARE @topnum VARCHAR(8000)

SET @topnum=''  --初始化變量 @sql

select @topnum= @topnum+',[' + convert (varchar(20),TopNum)+']' FROM #GoodsDestination GROUP BY TopNum order by TopNum --變量多值賦值

SET @topnum= STUFF(@topnum,1,1,'')--去掉首個','

select fEventDay as  EventDayF ,[fRoadName] as RoadNameF,[fFreight] as Freight
,'Freight'+convert(varchar(2), row_number() over(partition by [fEventDay],[fRoadName]  order by [fFreight] desc,[fDestination])) as TopNumF
into #GoodsDestinationF
FROM  [TOCC].[dbo].[tGoodsDestination]  WITH(INDEX(Index_Day)) where 1=1-- and fEventDay=20170320
group by [fEventDay],[fRoadName],[fDestination],[fFreight] 
order by [fEventDay],[fRoadName],[fFreight] desc,[fDestination]

DECLARE @topnumf VARCHAR(8000)

SET @topnumf=''  --初始化變量 @sql

select @topnumf= @topnumf+',[' + convert (varchar(20),TopNumF)+']' FROM #GoodsDestinationF GROUP BY TopNumF order by TopNumF --變量多值賦值

SET @topnumf= STUFF(@topnumf,1,1,'')--去掉首個','


DECLARE @strSql VARCHAR(8000)

SET @strSql='select * from ('  --初始化變量 @sql

SET @strSql= @strSql+ '(select  EventDay, RoadName'
--
set	@strSql = @strSql+ ','+@topnum

   
set	@strSql = @strSql+'from #GoodsDestination pivot (max(Destination) for TopNum in ('+@topnum+'))a  where 1=1'

if @S_Day is not null and @S_Day<>''
	set	@strSql = @strSql+' and EventDay '+@S_Day+'';

if @E_Day is not null and  @E_Day<>''
	set	@strSql = @strSql+' and EventDay '+@E_Day+''; 

if @RoadName is not null and @RoadName<>''
	set	@strSql = @strSql+' and RoadName in ('+@RoadName+')'; 

if 	@Destination is not null and 	@Destination<>''
	set	@strSql = @strSql+' and Destination in ('+	@Destination+')'; 

 
set @strSql = @strSql+') d';
set @strSql = @strSql+' left join ';
SET @strSql= @strSql+ '(select  EventDayF, RoadNameF'
--
set	@strSql = @strSql+ ','+@topnumf

   
set	@strSql = @strSql+'from #GoodsDestinationF pivot (max(Freight) for TopNumF in ('+@topnumf+')) a  where 1=1'

if @S_Day is not null and @S_Day<>''
	set	@strSql = @strSql+' and EventDay '+@S_Day+'';

if @E_Day is not null and  @E_Day<>''
	set	@strSql = @strSql+' and EventDay '+@E_Day+''; 

if @RoadName is not null and @RoadName<>''
	set	@strSql = @strSql+' and RoadName in ('+@RoadName+')'; 

if 	@Destination is not null and 	@Destination<>''
	set	@strSql = @strSql+' and Destination in ('+	@Destination+')'; 

 
set @strSql = @strSql+') f';
 set @strSql = @strSql+' on d.EventDay=f.EventDayF and d.RoadName=f.RoadNameF ';
 set @strSql = @strSql+')  ';
 if 	@order is not null and 	@order<>''
	set @strSql = @strSql+@order
else
	set @strSql = @strSql+' order by  Eventday, RoadName'
PRINT @strSql

exec(@strSql)
END

 

EventDay

RoadName

Destination1

Destination10

Destination2

Destination3

Destination4

Destination5

Destination6

Destination7

Destination8

Destination9

Freight1

Freight10

Freight2

Freight3

Freight4

Freight5

Freight6

Freight7

Freight8

Freight9

20150304

繞城高速

南通

NULL

蘇州

鹽城

連雲港

徐州

常州

南京

無錫

鎮江

673

NULL

673

673

547

547

396

396

396

396

20150304

蘇嘉杭

常州

NULL

南通

蘇州

無錫

連雲港

徐州

鹽城

南京

鎮江

533

NULL

533

533

533

406

406

406

255

255

20150305

繞城高速

淮安

鹽城

連雲港

徐州

常州

南京

鎮江

南通

蘇州

無錫

892

244

892

892

741

741

741

244

244

244

20150305

蘇嘉杭

常州

連雲港

蘇州

無錫

鎮江

南京

淮安

南通

徐州

鹽城

878

255

878

878

878

601

382

382

382

382

但是有BUG,由於目的地和運量是分別在兩個查詢輸出,同時,列的數量不確定,合並時沒法按要求輸出

由此還帶來另一個問題--排序時,以字符串形式的Destination10會排在Destination2的前面,實際應該在最后一列。

不知道有什么辦法可以解決,歡迎大家指教,謝謝!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM