Simplifying what I'm doing somewhat, as an example, say I have the following tables:
declare @elements table (id int, name nvarchar(20))
insert into @elements (id, name) values (1, 'FirstName')
insert into @elements (id, name) values (2, 'Surname')
insert into @elements (id, name) values (3, 'Address')
declare @values table (id int, value nvarchar(20), elementId int)
insert into @values (id, value, elementId) values (1, 'XXX', 1)
insert into @values (id, value, elementId) values (2, 'YYY', 2)
insert into @values (id, value, elementId) values (3, 'ZZZ', 3)
which simply defines a table of element names that could be dynamic, against which are defined a table of values.
What I would like is to generate XML in the following form, where the values of the @elements table become the element names, and the values of the @values table become the values.
<Customer>
<FirstName>XXX</FirstName>
<Surname>YYY</Surname>
<Address>ZZZ<Address>
</Customer>
However my efforts with for xml
so far are not going so well:
select e.name, v.value from @elements e
inner join @values v on v.elementId = e.id
for xml path(''), root('customer')
returns
<customer>
<name>FirstName</name>
<value>XXX</value>
<name>Surname</name>
<value>YYY</value>
<name>Address</name>
<value>ZZZ</value>
</customer>
for xml auto
returns
<customer>
<e name="FirstName">
<v value="XXX" />
</e>
<e name="Surname">
<v value="YYY" />
</e>
<e name="Address">
<v value="ZZZ" />
</e>
</customer>
for xml raw
returns
<customer>
<row name="FirstName" value="XXX" />
<row name="Surname" value="YYY" />
<row name="Address" value="ZZZ" />
</customer>
Is there a way I can get the values from a column to output as element names? I'm sure I'm missing something obviously simple here.
It's cheezy but it works...
select
cast('<' + name + '>' + value + '</' + name + '>' as xml)
from @values v
join @elements e on v.id = e.id
for xml path(''), root('Customer')
--- results ---
<Customer>
<FirstName>XXX</FirstName>
<Surname>YYY</Surname>
<Address>ZZZ</Address>
</Customer>
You are trying to model the dreaded semantic database (Entity-Attribute-Value). Read this paper to at least get you started on the right path: Best Practices for Semantic Data Modeling for Performance and Scalability
Technically, this is the query you're looking for:
select * from (
select name, value
from @values v
join @elements e on v.id = e.id) ve
pivot (max(value)
for name in ([FirstName], [Surname], [Address])) as p
for xml path('Customer')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With