First i manipulate the data into required format
IF OBJECT_ID('tempdb..##Getdata')IS NOT NULL
DROP TABLE ##Getdata
;With cte(Person, Color)
AS
(
SELECT 'Alex' , 'red' UNION ALL
SELECT 'Alex' , 'blue' UNION ALL
SELECT 'Alex' , 'orange' UNION ALL
SELECT 'Mike' , 'green' UNION ALL
SELECT 'Tom' , 'blue' UNION ALL
SELECT 'Tom' , 'black'
)
,Cte_Final
AS
(
SELECT DENSE_RANK()OVER(ORDER BY Person )AS Rnk
,Person
,Color
,'Color_'+CAST(DENSE_RANK()OVER(ORDER BY Person ) AS VARCHAR(2)) AS ColrCol
FROM cte
)
SELECT DISTINCT Rnk
,Person
,ColrCol
,STUFF((SELECT DISTINCT ', '+Color
FROM Cte_Final i WHERE i.Rnk=o.Rnk
FOR XML PATH ('')),1,1,'') AS
Color
INTO ##Getdata
FROM Cte_Final o
Using Dynamic Sql i get the expected result
DECLARE @COlumn nvarchar(max),@Sql nvarchar(max)
SELECT @COlumn=STUFF((SELECT DISTINCT ', '+'Split.a.value(''/S['+CAST(Rnk AS VARCHAR(2))+']'''+','+'''nvarchar(100)'''+') As ' + QUOTENAME(ColrCol )
FROM ##Getdata i
FOR XML PATH ('')),1,1,'')
SET @Sql='SELECT DISTINCT Person,'+@COlumn+' FROM
(
SELECT Person,
CAST(''<S>''+REPLACE (Color,'','',''</S><S>'')+''</S>'' AS XML ) AS Color
FROM ##Getdata
) AS A
CROSS APPLY Color.nodes(''S'') AS Split(a)
'
PRINT @Sql
EXEC(@Sql)
Result
Person Color_1 Color_2 Color_3
--------------------------------
Alex blue orange red
Mike green NULL NULL
Tom black blue NULL
view demo from below link
Expected Result for your data