When using XML path for aggregation, many times I need different strings which are based on the same set. Consider this example (script at the end):
+-----------+-----------+------------+
| firstname | thing | val |
+-----------+-----------+------------+
| mike | Tesla | 50000 |
| mike | Mona Lisa | 3000000000 |
+-----------+-----------+------------+
I want this result set returned:
+-----------+---------------------------------------------+------------------------------------------------------------------------+
| firstname | what_I_say_to_friends | what_I_say_to_finance |
+-----------+---------------------------------------------+------------------------------------------------------------------------+
| Mike | My friend Mike owns a Tesla and a Mona Lisa | My friend Mike owns a Tesla priced 50000 and a Mona Lisa priced 3e+009 |
+-----------+---------------------------------------------+------------------------------------------------------------------------+
I know how to do this using two different xml-path subqueries. But, since the only thing that changes is the choice of data to show (select), and not the underlying rows, is there any way to do it with a single xml path?
Data construction & dual xml query:
create table friend ( firstname nvarchar(50) )
insert friend values ('Mike')
create table owns
(
firstname nvarchar(50)
,thing nvarchar(50)
,val float
)
insert owns values
('mike','Tesla',50000),('mike','Mona Lisa',3000000000)
select
f.firstname
,'My friend '+f.firstname+' owns a '+q1.collection_no_value as what_I_say_to_friends
,'My friend '+f.firstname+' owns a '+q2.collection_with_value as what_I_say_to_finance
from
friend f
cross apply
(
select
stuff
(
(
select ' and a ' + o.thing
from owns o
where o.firstname=f.firstname
FOR XML PATH(''), TYPE
).value('.','nvarchar(max)')
,1,7,''
) as collection_no_value
) as q1
cross apply
(
select
stuff
(
(
select ' and a ' + o.thing+' priced '+convert(nvarchar(max),val)
from owns o
where o.firstname=f.firstname
FOR XML PATH(''), TYPE
).value('.','nvarchar(max)')
,1,7, ''
) as collection_with_value
) as q2
FOR XML PATHis the pre SQL Server 2017 solution toSTRING_AGG, however, you need to use 1 sub query per aggregation. If you don't want sub queries, you'll need to useSTRING_AGGon a version of SQL Server that supports it (2017+).'and a Mona Lisa priced 3e+009'strongly suggests your columnvalis being stored in a floating point data type (float/real). This is a really bad idea. Floating point values are not accurate values and most certainly should not be used for storing monetary values.