单元格并

单元格合并拉。
交叉表.
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go


/*Function: p_cross_table_standard
**Copyright (c) ---------------Dongguan Zensee Printing Ltd----------------
**Creator: IT_Micro.
**Create date: 2009/08/12
**Modify:
**Modify date:
**Description:
根據提供的Sql語句生成交叉表數據
**Parameters:
@sql value: Sql語句.
@column_fixed value: 左邊顯示的固定的列名(多個之間用逗號隔開)
@column_cross value: 需要交叉的列名.
@cell_value value: 交叉單元格顯示值(字段名或指定固定值).
@cell_value_type value: 交叉單元格顯示值類型(name-字段, value-固定值).
@column_header value: 交叉數據單元格列頭字段.
*/
ALTER PROCEDURE [dbo].[p_cross_table_standard]
@sql varchar(8000),
@column_fixed varchar(300),
@column_cross varchar(50),
@cell_value varchar(50),
@cell_value_type varchar(10),
@column_header varchar(50)
AS
begin
declare @table_name_1 varchar(50),
@table_name_2 varchar(50),
@table_name_3 varchar(50),
@sql_temp_1 nvarchar(max),
@sql_temp_2 nvarchar(max),
@index int,
@rows int,
@columns int
declare @field_name varchar(100),
@field_value varchar(1000),
@row_value varchar(50),
@cross_value varchar(300),
@sys_cross_rowindex varchar(10),
@condition_update varchar(1000),
@condition_temp varchar(1000)

--把左邊顯示的固定的列名寫入臨時表
select * into #t_1 from dbo.f_char_split_to_table(@column_fixed, ',')

create index idx_t_1 on #t_1(value)

--創建全局臨時表1
set @table_name_1 = '##' + replace(convert(char(36), newid()), '-', '_')

--根據sql語句生成原始表數據
EXEC('SELECT M.*, identity(int,1,1) as sys_cross_rowindex INTO ' + @table_name_1 + ' FROM(' + @sql + ') AS M')

--臨時表1創建主鍵
exec ('ALTER TABLE ' + @table_name_1 + ' ADD CONSTRAINT PK_' + @table_name_1 + ' PRIMARY KEY CLUSTERED (sys_cross_rowindex) ON [PRIMARY]')

--創建全局臨時表2
set @table_name_2 = '##' + replace(convert(char(36),newid()), '-' ,'_') + 'cross'

---把需要交叉的所有字段加入到臨時表中
set @sql_temp_1 = 'select distinct ' + @column_cross + ',' + @column_header + ' as display from ' + @table_name_1 + ' order by '+ @column_cross
create table #field(field varchar(50), field_display varchar(100))
insert into #field exec(@sql_temp_1)

--取得交叉列縱向的數量
select @columns = count(field) from #field

--計算交叉值的數量
set @sql_temp_1 = 'select @rows = count(value) from #t_1'
exec sp_executesql @sql_temp_1, N'@rows int output', @rows output

--控制最大列數
if (@rows * @columns > 500)
begin
declare @max_rows int
set @max_rows = 500/@rows
delete #field
set @sql_temp_1 = 'select distinct top ' + cast(@max_rows as varchar) + ' ' + @column_cross + ' from ' + @table_name_1 + ' where isnull(' + @column_cross + ','''')!= '''''
insert into #field exec(@sql_temp_1)
end

--拼原樣輸出的行字段
set @sql_temp_1 = 'create table ' + @table_name_2 + '('

declare cur_read cursor local for
select value from #t_1
open cur_read
fetch next from cur_read into @field_name
while @@fetch_status=0
begin
set @sql_temp_1 = @sql_temp_1 + @field_name + ' varchar(50),'
fetch next from cur_read into @field_name
end
close cur_read
deallocate cur_read

--創建交叉臨時表
declare cur_read cursor local for select '[' + rtrim(ltrim(field)) + ']' from #field
open cur_read
fetch next from cur_read into @field_name
while @@fetch_status=0
begin
set @sql_temp_1 = @sql_temp_1 + @field_name + ' varchar(100),'

fetch next from cur_read into @field_name
end
close cur_read
deallocate cur_read

set @sql_temp_1 = left(@sql_temp_1, len(@sql_temp_1) - 1) + ')'

exec(@sql_temp_1)

--處理排序問題
--增加一個臨時表@table_name_3,主要是用來保持原SQL語句的排序順序
set @table_name_3 = '##' + replace(convert(char(36), newid()), '-', '_')
set @sql_temp_1 = 'select distinct ' + @column_fixed + ' into ' + @table_name_3 + ' from ' + @table_name_1 + ' where ' + @column_cross + ' in(select field from #field)'
exec(@sql_temp_1)

declare @join varchar(300)
set @join = ''
select @join = @join + 'A.' + value + '=B.' + value + ' and ' from #t_1

if (@join != '')
set @join = left(@join, len(@join) - 4)

--在臨時表@table_name_3中添加一個字段sys_cross_rowindex
exec ('alter table ' + @table_name_3 + ' add sys_cross_rowindex bigint null')

--把關聯字段的sys_cross_rowindex更新到臨時表中,以便排序時用
set @sql_temp_1 = 'update ' + @table_name_3 + ' set sys_cross_rowindex = B.sys_cross_rowindex from ' + @table_name_3 + ' A right join ' + @table_name_1 + ' B on ' + @join
exec (@sql_temp_1)

--把臨時表@table_name_3數據填充到臨時表@table_name_2
select @sql_temp_1 = 'insert into ' + @table_name_2 + '(' + @column_fixed + ') select ' + @column_fixed + ' from '+ @table_name_3 + ' order by sys_cross_rowindex'
exec(@sql_temp_1)

set @index = 1

set @condition_temp = ''

declare cur_read_date cursor local for
select value from #t_1
open cur_read_date
fetch next from cur_read_date into @field_name
while @@fetch_status = 0
begin
if (@condition_temp = '')
set @condition_temp = @condition_temp + ''' where ' + @field_name + '='''''' + cast(' + @field_name + ' as varchar)'
else
set @condition_temp = @condition_temp + ' + '''''' and ' + @field_name + '='''''' + cast(' + @field_name + ' as varchar)'

fetch next from cur_read_date into @field_name
end
close cur_read_date
deallocate cur_read_date

set @condition_temp = @condition_temp + '+ '''''''''

--填充交叉單元格
exec('declare cur_cross cursor global for select ''['' + rtrim(ltrim(cast('
+ @column_cross + ' as varchar)))+ '']'', cast(sys_cross_rowindex as varchar)
from ' + @table_name_1 + ' where ' + @column_cross
+ ' in(select field from #field)')
open cur_cross
fetch next from cur_cross into @cross_value, @sys_cross_rowindex
while @@fetch_status=0
begin
--以@column_fixed的列為基准作為更新條件
set @sql_temp_2 = 'select @condition_update = (' + @condition_temp + ') from ' + @table_name_1 + ' where sys_cross_rowindex = ' + cast(@index as varchar)
exec sp_executesql @sql_temp_2, N'@condition_update varchar(1000) output', @condition_update output

--取得填充交叉單元格的值
if (@cell_value_type = 'name')
begin
set @sql_temp_2 = 'select @field_value = ' + @cell_value + ' from ' + @table_name_1 + ' where sys_cross_rowindex = ' + @sys_cross_rowindex
exec sp_executesql @sql_temp_2, N'@field_value varchar(1000) output', @field_value output
end
else
begin
set @field_value = @cell_value
end

--更新交叉單元格的值
exec('update ' + @table_name_2 + ' set ' + @cross_value + ' = ''' + @field_value + '''  ' + @condition_update)

set @index = @index + 1

fetch next from cur_cross into @cross_value, @sys_cross_rowindex
end
close cur_cross
deallocate cur_cross

exec('select * from ' + @table_name_2)

drop table #t_1
drop table #field
exec('drop table '+ @table_name_1)
exec('drop table '+ @table_name_2)
exec('drop table '+ @table_name_3)
end

你可能感兴趣的:(sql,F#,Go)