You could also use a pivot to achieve this; if you know the columns you can enter them in the script, but if not, you can use dynamic sql (there are reasons why you might want to avoid the dynamic solution).
The advantage of this route is that you can enter the column list in a table and then changes to that table will result in changes to your output with change to the script involved. The disadvantages are all those associated with dynamic SQL.
In the interests of variation, here is a dynamic SQL solution using temp tables to hold your data, since a different possibility has been provided:
-- set up your data
CREATE TABLE #MyTab (Name VARCHAR(4), Amount INT, ReasonId INT)
CREATE TABLE #AllPossibleReasons (Id INT,Label VARCHAR(10))
INSERT #AllPossibleReasons
VALUES
     (1,'Reason1')
    ,(2,'Reason2')
    ,(3,'Reason3')
    ,(4,'Reason4')
    ,(5,'Reason5')
    ,(6,'Reason6')
    ,(7,'Reason7')
    ,(8,'Reason8')
    ,(9,'Reason9')
INSERT #MyTab
VALUES
     ('Bob',7,7)
    ,('Bob',8,6)
    ,('John',2,8)
    ,('John',5,9)
    ,('John',3,9)
    ,('John',8,4)
-----------------------------------------------------------------------------
-- The actual query
DECLARE @ReasonList VARCHAR(MAX) = ''
DECLARE @SQL VARCHAR(MAX)
SELECT @ReasonList = @ReasonList + ',' + QUOTENAME(Label)
FROM #AllPossibleReasons
SET @ReasonList = SUBSTRING(@ReasonList,2,LEN(@ReasonList))
SET @SQL = 
'SELECT Name,Value,' + @ReasonList + ' FROM
    (SELECT 
        M.Name,SUM(Amount) AS This, Label, SUM(Total.Value) AS Value
     FROM
            #MyTab                              AS M
     INNER JOIN #AllPossibleReasons             AS Reason   ON M.ReasonId = Reason.Id
     INNER JOIN(SELECT T.Name, SUM(Amount)Value
                FROM #MyTab T GROUP BY T.Name)      AS Total    ON M.Name = Total.Name
     GROUP BY M.Name, Reason.Label) AS Up
    PIVOT (SUM(THis) FOR Label IN (' + @ReasonList + ')) AS Pvt'
EXEC (@SQL)
DROP TABLE #AllPossibleReasons
DROP TABLE #MyTab