TSQL Help

This is why you need a Tally table. The query I posted seem to be giving the results that you are asking for, at least as I understood it. I have modified the code below to replace NULL with zeros.

-- First, create a sample table. 
-- When you post a question, it would be very helpful if you post DDL such as this 
-- that someone can copy and paste to run and write queries against.
-- Otherwise, the code posted would most likely be untested code.

CREATE TABLE #tmp( SDate DATETIME , TotalCalls INT)

INSERT INTO #tmp VALUES
('2015-07-28 11:11:10.420',11),
('2015-07-28 11:53:10.000',3),
('2015-07-29 12:10:10.420',9),
('2015-07-29 12:23:17.000',1),
('2015-07-29 11:23:17.000',6);

-- Create Tally table 
CREATE TABLE #Tally(N INT NOT NULL PRIMARY KEY);

INSERT INTO #Tally 
        ( N )
SELECT TOP 10000
        ROW_NUMBER() OVER ( ORDER BY t1.number )-1 AS N
FROM    master..spt_values t1
        CROSS JOIN master..spt_values t2

-- Query for 28th and 29th

DECLARE 
	@startDate DATETIME = '20150728',
	@endDate DATETIME = '20150729';
	

SELECT
	DATEADD(hh,N,@startDate) [StartHour],
	COALESCE(SUM(TotalCalls),0) AS TotalCalls
FROM
	#Tally t
	LEFT JOIN #tmp d ON 
		d.SDate >= DATEADD(hh,N,@startDate)
		AND d.SDate < DATEADD(hh,N+1,@startDate)
WHERE
	DATEADD(hh,N-24,@startDate) <= @endDate
GROUP BY
	DATEADD(hh,N,@startDate)
ORDER BY 
	[StartHour] ;'

When I run this, I get 49 rows of output, most of which have TotalCalls = 0. The three rows with non-zeros is as follows

StartHour				TotalCalls
2015-07-28 11:00:00.000		14
2015-07-29 11:00:00.000		6
2015-07-29 12:00:00.000		10

Isn't that what you were asking for, or is it something else?