SQL:
--【Build Test Data】
create table #Tem_Table ([ID] int,[Subject] nvarchar(20),[Users] nvarchar(20));
insert into #Tem_Table ([ID],[Subject] ,[Users]) values
('1','Hi!','Anna')
,('2','Hi!','Peter')
,('3','Try','Jan')
,('4','Try','Peter')
,('5','Try','Jan')
,('6','Problem','Anna')
,('7','Problem','José')
,('7','Test','John')
,('9','Test','John')
,('10','Hi! ','Anna')
,('11','Hi! ','José')
,('12','Hi! ','Anna')
,('13','Hi! ','Joe')
;
--STEP 1 distinct and ROW_NUMBER
with distinct_table as (
select [Subject],[Users]
,ROW_NUMBER() OVER (PARTITION BY [Subject] order by [Users]) [rank]
from (
select distinct [Subject],[Users] from #Tem_Table
) T00
)
--STEP 2 Group by row_count
,group_table as (
select [Subject]
from distinct_table T
group by [Subject]
)
--STEP 3 Use Left Join and Rank
select
T.[Subject],T1.[Users] as User1, T2.[Users] as User2 , T3.[Users] as User3, T4.[Users] as User4
from group_table T
left join distinct_table T1 on T.[Subject] = T1.[Subject] and T1.[rank] = 1
left join distinct_table T2 on T.[Subject] = T2.[Subject] and T2.[rank] = 2
left join distinct_table T3 on T.[Subject] = T3.[Subject] and T3.[rank] = 3
left join distinct_table T4 on T.[Subject] = T4.[Subject] and T4.[rank] = 4
order by [Subject];
result:
-------------------- -------------------- -------------------- -------------------- --------------------
Hi! Anna Joe José Peter
Problem Anna José NULL NULL
Test John NULL NULL NULL
Try Jan Peter NULL NULL
Update the Dynamic version :
--STEP 1 distinct and ROW_NUMBER
SELECT * into #distinct_table from (
select [Subject],[Users]
,ROW_NUMBER() OVER (PARTITION BY [Subject] order by [Users]) [rank]
from (
select distinct [Subject],[Users] from #Tem_Table
) T00
)T;
--STEP 2 Group by row_count
SELECT * into #group_table from (
select [Subject] ,count(1) [count]
from #distinct_table T
group by [Subject]
)T;
--Use Exec
DECLARE @select_sql AS NVARCHAR(MAX) = ' select T.[Subject] ',
@join_sql AS NVARCHAR(MAX) = ' from #group_table T ',
@max_count INT = (SELECT max([count]) FROM #group_table),
@temp_string NVARCHAR(5),
@temp_string_addone NVARCHAR(5)
;
DECLARE @index int = 0 ;
WHILE @index < @max_count
BEGIN
sELECT @temp_string = Convert(nvarchar(10),@index);
sELECT @temp_string_addone = Convert(nvarchar(10),@index+1);
select @select_sql = @select_sql + ' , T'+@temp_string_addone+'.[Users] as User'+@temp_string_addone+' '
select @join_sql = @join_sql + 'left join #distinct_table T'+@temp_string_addone+' on T.[Subject] = T'+@temp_string_addone+'.[Subject] and T'+@temp_string_addone+'.[rank] = '+@temp_string_addone+' ';
SET @index = @index + 1;
END;
EXEC (@select_sql
+ @join_sql
+' order by [Subject]; ')
;