Вот пример, чтобы получить то, что вы хотите, используя динамический sql.
Обратите внимание, что тест CTE и временная таблица # tmp2 должны соответствовать вашим исходным таблицам.
create table #tmp (ID int, Related_ID int, Value nvarchar(50), Name nvarchar(50), rn int)
delete #tmp
create table #tmp2 (ID int, Name nvarchar(50), Email nvarchar(50))
delete #tmp2
;with test(ID, Related_ID, Value, Name)
as
(
select 1, 1, 'Z', 'Name1'
union all
select 2, 1, 'Y', 'Name2'
union all
select 3, 2, 'X', 'Name1'
union all
select 4, 2, 'W', 'Name2'
union all
select 5, 2, 'G', 'Name3'
)
insert into #tmp
select *, row_number() OVER (partition by Related_ID order by ID) as rn
from test
insert into #tmp2
select 1, 'A', 'a@b.c'
union all
select 2, 'B', 'b@c.d'
declare @d nvarchar(MAX)
,@e nvarchar(MAX)
SET @d = 'select a.ID, a.Name, a.Email '
SET @e = ',min(case b.rn when >rn< then Value else null end) as [Value>rn<]'
select @d = @d + (
select t from(
select distinct replace(@e,'>rn<', b.rn) as [text()]
from #tmp b
for xml path('')) c(t)
)
set @d = @d + '
from #tmp2 a
join #tmp b
on a.ID = b.Related_ID
group by a.ID, a.Name, a.Email'
exec sp_executesql @d
drop table #tmp
drop table #tmp2