因項目中常需要行轉列的統計報表,每次編寫時,均費一番功夫,今天特地花費幾個小時編寫了一套用於Sqlserver的 通用行轉列 存儲過程
采用sqlserver2000自帶的pubs示例庫,實驗目標:
將作者所寫的圖書價格 以橫向表格展示 如:
| 作者 | 書名1 | 書名2 | 書名3 | 書名4 |
| 張三 | 25.0 | 3.5 | ||
| 李四 | 89.0 | 54.30 |
1>首先查詢出作者對應的書名以及價格
Sql語句如下
select a.au_lname,c.title as colName,cast(price as nvarchar(50)) as result from authors a ,titleauthor b,titles c where a.au_id = b.au_id and c.title_id= b.title_id
如圖所示:
2>只需將sql語句放入存儲過程參數即可:
declare @temp nvarchar(500) set @temp = 'select a.au_lname as 作者,c.title as colName,cast(price as nvarchar(50)) as result from authors a ,titleauthor b,titles c where a.au_id = b.au_id and c.title_id= b.title_id ' exec CommonRowToCol @temp
執行效果
3>使用時,只需將要作為列名的字段定義為colname,將欲顯示的列定義為result即可
完整的存儲過程代碼如下:
create procedure dbo.CommonRowToCol
@sql nvarchar(4000)
as
begin
--必須包含colname列和result列(不區分大小寫),
--除colname列和result列 其余各列均會作為判別記錄唯一性的條件
create table #temp([序號] int IDENTITY(1,1))
declare @sqlTemp nvarchar(4000),@sql_select nvarchar(1000),@temp nvarchar(500)
declare @sql_All nvarchar(4000),@sql_Table nvarchar(1000),@sql_declare nvarchar(1000),@sql_Fetch nvarchar(1000) ,
@sql_id nvarchar(1000),@sql_id2 nvarchar(1000),@sql_insert nvarchar(1000),@sql_value nvarchar(1000)
set @sql_select = '' set @sql_All = '' set @sql_Table ='' set @sql_declare = '' set @sql_Fetch = ''
set @sql_id = '' set @sql_id2 = '' set @sql_insert='' set @sql_value = ''
set @sql = lower(LTRIM(@sql))
set @sqlTemp = @sql
set @sqlTemp = ' select top 0 * into #tempTbl from ('+@sqlTemp+')z '+
' select @temp = Name+'',''+@temp from ( select top 1111 name from tempdb..syscolumns where id = object_id(N''tempdb..#tempTbl'') order by colorder )z '
EXECUTE sp_executesql @sqlTemp, N'@temp nvarchar(1000) output',@sql_select output
while charindex(',',@sql_select) > 0
begin
select @temp = lower(LEFT(@sql_select,charindex(',',@sql_select)-1))
select @sql_select = stuff(@sql_select,1,charindex(',',@sql_select),'')
if (@temp <> 'colname') and (@temp<>'result')
begin
set @sql_Table = ' ['+@temp+'] nvarchar(1000),' + @sql_Table
set @sql_insert = ' ['+@temp+'],' + @sql_insert
set @sql_value ='isnull(@'+@temp+',''''),'+@sql_value
set @sql_id = ' ['+@temp+'] = isnull(@'+@temp+','''') and' + @sql_id
set @sql_id2 = ' ['+@temp+'] = isnull(''''''+@'+@temp+'+'''''' ,'''''''') and' + @sql_id2
end;
set @sql_declare = ' @'+@temp+' nvarchar(1000),'+@sql_declare
set @sql_Fetch = ' @'+@temp+','+@sql_Fetch
end;
set @sql_Table = 'ALTER TABLE #temp ADD ' +left(@sql_Table,len(@sql_table)-1)+' '
set @sql_declare = 'declare @sqlTemp nvarchar(4000),' +left(@sql_declare,len(@sql_declare)-1) + ' '
set @sql_Fetch = left(@sql_Fetch,len(@sql_fetch)-1) + ' '
set @sql_id = left(@sql_id,len(@sql_id)-3) + ' '
set @sql_id2 = left(@sql_id2,len(@sql_id2)-3) + ' '
set @sql_insert = left(@sql_insert,len(@sql_insert)-1) + ' '
set @sql_value = left(@sql_value,len(@sql_value)-1) + ' '
set @sql_All = @sql_declare +
' Declare myCur Cursor For '+ @sql + ' Open myCur Fetch NEXT From myCur Into '+ @sql_Fetch+
' While @@fetch_status=0 Begin '+
' if not exists(select * from tempdb..syscolumns where id = object_id(N''tempdb..#temp'') and name = @colName)
begin
set @sqlTemp =''alter table #temp add [''+@colName+''] nvarchar(4000) ''
exec(@sqlTemp)
end
if not exists(select * from #temp where '+@sql_id+')
begin
insert into #temp('+@sql_insert+') values('+@sql_value+')
end
set @sqlTemp ='' update #temp set [''+@colName+''] = isnull(''''''+@result+'''''','''''''') where ' + @sql_id2+'''
exec(@sqlTemp)
Fetch NEXT From myCur Into '+ @sql_Fetch+
'end
Close myCur
Deallocate myCur
select * from #temp
'
exec (@sql_Table)
exec(@sql_All)
end
4>以上代碼在sqlserver2000,2005,2008測試通過.
5>交流請留言,轉載請標注

![@YEZVR}Y@]`AXU{`A$)_E$G @YEZVR}Y@]`AXU{`A$)_E$G](/image/aHR0cHM6Ly9pbWFnZXMwLmNuYmxvZ3MuY29tL2Jsb2cvNzgyMzgvMjAxMzEwLzExMTgzMTExLWQzNjU1NTVmM2Y1NzQyOWE4NzBmY2Y1YWM2NmFlNzJmLmpwZw==.png)
