Reputation: 568
I have a table called userInfo that has data similar to the following:
Id, Field, Value
---------------------
1, FirstName, John
1, LastName, Smith
1, Age, 25
1, Gender, Male
2, FirstName, Jane
2, LastName, Smythe
2, Age, 24
2, Gender, Female
What I need is some T-SQL that will produce a single row for each Id with the following structure:
Row:1
<FieldValues>
<FirstName>John</FirstName>
<LastName>Smith</LastName>
<Age>25</Age>
<Gender>Male</Gender>
</FieldValues>
Row:2
<FieldValues>
<FirstName>Jane</FirstName>
<LastName>Smythe</LastName>
<Age>24</Age>
<Gender>Female</Gender>
</FieldValues>
I have tried a couple of things to get this but can't get figure this out.
Edit: The list of Fields I provided here (i.e. FirstName, LastName, etc) is not a static list of fields. I will be adding and taking away from this list all the time so the query would be able to handle this automatically). Ideally I could use something like FOR XML PATH('FieldValues')
Upvotes: 2
Views: 108
Reputation: 138960
You can build your XML as a string using for xml path('')
and then cast to XML.
select T.Id,
cast('<FieldValues>' + (
select '<'+T2.Field+'>'+
(select T2.Value as '*' for xml path(''))+
'</'+T2.Field+'>'
from dbo.YourTable as T2
where T.Id = T2.Id
for xml path(''), type
).value('text()[1]', 'varchar(max)') +
'</FieldValues>' as xml) as FieldValues
from dbo.YourTable as T
group by T.Id;
This part (select T2.Value as '*' for xml path(''))
is there to take care of characters that needs to be entities in the value like &
.
Upvotes: 1
Reputation: 70523
Here is one way:
SELECT '<FieldValues>'+
'<FirstName>'+fn.Value +'</FirstName>' +
'<LastName>'+ln.Value +'</LastName>' +
'<Age>'+age.Value +'</Age>' +
'<Gender>'+gender.Value +'</Gender>' +
'</FieldValues>
FROM (SELECT DISTINCT ID FROM userInfo) t
JOIN userInfo fn ON t.ID = fn.ID and fn.Field = 'FirstName'
JOIN userInfo ln ON t.ID = ln.ID and ln.Field = 'LastName'
JOIN userInfo age ON t.ID = age.ID and age.Field = 'Age'
JOIN userInfo gender ON t.ID = gender.ID and gender.Field = 'Gender'
How this works:
First I create table of just the unique ID numbers.
SELECT DISTINCT ID FROM table
Then I use this table to join back to the main table for each field. (Each of these joins will have only one row per ID.)
JOIN table fn ON t.ID = fn.ID and fn.Field = 'FirstName'
JOIN table ln ON t.ID = ln.ID and ln.Field = 'LastName'
JOIN table age ON t.ID = age.ID and age.Field = 'Age'
JOIN table gender ON t.ID = gender.ID and gender.Field = 'Gender'
Finally I create a string formatted as you need.
'<FieldValues>'+
'<FirstName>'+fn.Value +'</FirstName>' +
'<LastName>'+ln.Value +'</LastName>' +
'<Age>'+age.Value +'</Age>' +
'<Gender>'+gender.Value +'</Gender>' +
'</FieldValues>
An additional note: It is recommended to not use Camel Case on your xml since xml is case sensitive any use of case is a pain -- most just use all lower case.
Upvotes: 0