Translate

Saturday, December 1, 2012

Rows to Columns with XQuery

SET NOCOUNT ON
DECLARE
  @cols NVARCHAR(MAX)
  ,@query NVARCHAR(MAX) = ''
  ,@str NVARCHAR(MAX) = ''
  ,@xml XML
  ,@cnt int
  ,@max int
;
DECLARE @tmpStrTable TABLE (RowID int identity(1,1), String nvarchar(1000))

-- Get XML
SET @xml = (SELECT [XML] FROM [Table] WHERE [ID] = (SELECT MAX([ID]) FROM [Table] GROUP BY [ID]))


-- Get columns
INSERT @tmpStrTable (String)
    SELECT r.value('local-name(.)', 'varchar(max)')
    FROM @xml.nodes('/*/*[1]/*') a (r)

-- Build Dynamic query
-- include retrieving XML again

select @query = 'DECLARE @xml XML ' +char(13)+char(10)
select @query = @query + 'SET @xml = (SELECT [XML] FROM [Table] WHERE [ID] = (SELECT MAX([ID]) FROM [Table] GROUP BY [ID])) ' +char(13)+char(10)
SELECT @query = @query + N'SELECT '
select @max = (SELECT COUNT(*) FROM @tmpStrTable)SELECT @cnt = 1
while @cnt <= @max
    BEGIN
    select @str = (SELECT String FROM @tmpStrTable WHERE (RowID = @cnt))
    if @cnt = 1
        select @query = @query + N'ent.query(''' + @str + N''').value(''.'',''VARCHAR(max)'') [' + @str + N']'
    else
        select @query = @query + N', ent.query(''' + @str + N''').value(''.'',''VARCHAR(max)'') [' + @str + N']'
    SELECT @cnt = @cnt + 1
    END
SELECT @query = @query + N' FROM @xml.nodes(''/*/*'') Col(ent)'

--print @query
EXEC sp_executesql @query