Элегантно в один запрос не получится, т.к. группировать придется по вычисляемому полю.
Если данных много, а запрос будет выполняться часто, я бы сделал таблицу типа "справочник часов" и джойнил бы с ней. Если данных мало, то можно и на лету соорудить, что-то типа:
declare @StartDate datetime, @EndDate datetime;
select @StartDate = '20130203 13:00', @EndDate = '20130204 15:00';
declare @t table (
Id int identity (1,1) primary key,
MeasureDate datetime not null,
Value money not null
);
insert into @t (MeasureDate, Value)
values ('20130203 13:00', 25),
('20130203 13:30', 124),
('20130203 14:00', 71),
('20130203 14:30', 89);
select * from @t order by MeasureDate;
select ca.DT, sum(t.Value) as [Amount]
from @t t
inner join (
select top (datediff(hh, @StartDate, @EndDate) + 1) dateadd(hh, row_number() over(order by v.type) - 1, @StartDate) as [DT]
from master.dbo.spt_values v--, master.dbo.spt_values v2
order by DT
) ca on t.MeasureDate <= ca.DT and t.MeasureDate > dateadd(hh, -1, ca.DT)
group by ca.DT;
Только план все равно отстойный, как видите, ибо row_number() нумерует все строки, а не только те, которые подпадают под условие в top (). Лучше хотя бы табличную переменную объявить и сгрузить в нее результат подзапроса. Все быстрее будет.