Currently I am trying to convert vertical data structure to horizontal data dynamically by implementing a cursor in the stored procedure. However, the execution time takes too long. I am trying to find a way to optimise this approach. What is the better way to use other than Cursor? Note: PIVOT cant be used because of scattered data mapping. This is my current code with sample data and expected output:
What I have done so far: There are three temporary tables #tablestructure, #raw and #dsid. #Tablestruture contains all the columns under destfieldname which are needed to create a table. Then once it is created, we need to take the contents from #raw and insert it into the new table which has been created based on the row and column number
#tablestructure
| desttablename | destfieldname | datatype |
|---|---|---|
| * | subjectnumber | int |
| sample | personame | nvarchar(20) |
| sample | personlocation | nvarchar(20) |
#raw table
| rownumber | columnnumber | fieldname | contents |
|---|---|---|---|
| 1 | 1 | subjectnumber | 132516352 |
| 1 | 2 | personname | Alex |
| 2 | 1 | subjectnumber | 132516353 |
| 2 | 3 | personlocation | Canada |
| 1 | 3 | personlocation | Australia |
| 2 | 2 | personname | John |
#DSID Table
| projectid | respondentfieldname | debug | fileincludedheaders |
|---|---|---|---|
| 123 | subjectnumber | NULL | 1 |
Expected output
| Subjectnumber | PersonName | Personlocation |
|---|---|---|
| 132516352 | Alex | Australia |
| 132516353 | John | Canada |
declare createSQL cursor for
select distinct 'drop table TestTmp.dbo.' + t.destname as droptableSQL,
'CREATE TABLE TestTmp.dbo.' + t.destname + ' (' + stuff((
select ',[' + destfieldname + '] ' + f.datatype from #tableStructure f
where (f.desttablename in (t.desttablename, '*'))
group by destfieldname, f.datatype)
for xml path ('')),1,1,'') + ', [sequenceID] int, [subsequenceID] int)' as createTableSQL,
'insert into VectorNormalizerTmp.dbo.' + t.desttablename + @tablesuffix + '([' + replace(replace(respondentidfieldname,']',''),'[','') + '],sequenceid, subsequenceid)
SELECT a.contents, b.sequenceid, b.subsequenceid from (select contents from #raw where fieldname = ''' + respondentidfieldname + ''') a
CROSS JOIN (select sequenceid, subsequenceid from #rowUniques where desttablename = ''' + desttablename +''') b ' as appendEmptyRowsSQL,
'create index idx' + t.desttablename + @tablesuffix + ' on VectorNormalizerTmp.dbo.' + desttablename + @tablesuffix + '([' + respondentidfieldname + '],sequenceid, subsequenceid)' as idxSQL
from (select distinct desttablename from #tablestructure where desttablename = 'Screener') t
cross join (select respondentidfieldname, debug from #dsid) d
declare @sqltorun nvarchar(max);
declare @sqltorun2 nvarchar(max);
declare @sqltorun3 nvarchar(max);
declare @sqltorun4 nvarchar(max);
open createSQL
fetch next from createSQL into @sqltorun, @sqltorun2, @sqltorun3, @sqltorun4
while @@FETCH_STATUS = 0
begin
begin try
--print @sqltorun
EXECUTE sp_executesql @sqltorun
end try
begin catch
--print '!!ERROR: ' + ERROR_MESSAGE()
end catch
print @sqltorun2
EXECUTE sp_executesql @sqltorun2
print @sqltorun3
EXECUTE sp_executesql @sqltorun3
--print @sqltorun4
begin try
EXECUTE sp_executesql @sqltorun4
end try
begin catch
--print '!!ERROR: ' + ERROR_MESSAGE()
end catch
fetch next from createSQL into @sqltorun, @sqltorun2, @sqltorun3, @sqltorun4
end
close createSQL
deallocate createSQL