Сумма строк

Etamin419
Дата: 21.02.2013 07:47:05
Добрый день.
Неожиданно застал врасплох запрос, который не могу не как придумать. есть данные получасовок и нужно суммировать так, чтобы 30 минутные значения не отображались в выводе, но данные их учитывались
т.е.
Дата Значения
13:30 110
14:00 220

При сумме должно получится так
Дата Значения
14:00 330
HandKot
Дата: 21.02.2013 08:03:07
Etamin419,
применить соответствующую группировку
euthanatos
Дата: 21.02.2013 08:10:35
А мне пока видится только решение выполнить это отдельной функцией, которая за первый проход наполнит временную табличную переменную значениями с целыми часами (как '14:00', '15:00', '16:00'), а во второй проход пройдется курсором по получившейся таблице и просуммирует соответствующие ячейки из первой, которые находятся в интервалах второй таблицы.

Хотя вероятно при достаточно развитых мозгах обычный селект решает эту проблему более элегантно
Добрый Э - Эх
Дата: 21.02.2013 08:33:39
euthanatos,

то есть проверить время на целый или половинный час и в случае "половины" округлить до ближайшего большего целого часа - не судьба?
AxuliON
Дата: 21.02.2013 09:00:14
HandKot
Etamin419,
применить соответствующую группировку

Это 5+
Тут все просто же
with cte as
(
select '2013-02-21 13:00' as dt, 666 as val
union
select '2013-02-21 13:30' as dt, 111 as val
union
select '2013-02-21 14:00' as dt, 222 as val
union
select '2013-02-21 14:30' as dt, 333 as val
)
select DATEPART(hh, DATEADD(mi, -1, dt)), SUM(val) from cte -- Вычитаем минуту, чтобы час попал в предыдущий отчетный
group by DATEPART(hh, DATEADD(mi, -1, dt))
AxuliON
Дата: 21.02.2013 09:06:54
Etamin419
Добрый день.
Неожиданно застал врасплох запрос, который не могу не как придумать. есть данные получасовок и нужно суммировать так, чтобы 30 минутные значения не отображались в выводе, но данные их учитывались
т.е.
Дата Значения
13:30 110
14:00 220

При сумме должно получится так
Дата Значения
14:00 330

Да не заметил, у Вас час отчетный идет 14:00
Тогда надо будет +1 сделать
Если надо по дате и времени группировать - то разобраться сами должны.
Я лишь путь указал (цэ) "не моё"
with cte as
(
select '2013-02-21 13:00' as dt, 666 as val
union
select '2013-02-21 13:30' as dt, 111 as val
union
select '2013-02-21 14:00' as dt, 222 as val
union
select '2013-02-21 14:30' as dt, 333 as val
)
select DATEPART(hh, DATEADD(mi, -1, dt)) +1, SUM(val) from cte -- Вычитаем минуту, чтобы час попал в предыдущий отчетный
group by DATEPART(hh, DATEADD(mi, -1, dt))+1
Ennor Tiegael
Дата: 21.02.2013 09:09:07
Элегантно в один запрос не получится, т.к. группировать придется по вычисляемому полю.

Если данных много, а запрос будет выполняться часто, я бы сделал таблицу типа "справочник часов" и джойнил бы с ней. Если данных мало, то можно и на лету соорудить, что-то типа:
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 (). Лучше хотя бы табличную переменную объявить и сгрузить в нее результат подзапроса. Все быстрее будет.
iap
Дата: 21.02.2013 09:13:48
Группировать по часам, но для [Дата] выводить MAX([Дата]), а для [Значения] - SUM([Значения])
AxuliON
Дата: 21.02.2013 09:16:03
Ennor Tiegael,

Говнокодом попахивает....
Etamin419
Дата: 21.02.2013 09:51:02
AxuliON
Да не заметил, у Вас час отчетный идет 14:00
Тогда надо будет +1 сделать
Если надо по дате и времени группировать - то разобраться сами должны.
Я лишь путь указал (цэ) "не моё"
with cte as
(
select '2013-02-21 13:00' as dt, 666 as val
union
select '2013-02-21 13:30' as dt, 111 as val
union
select '2013-02-21 14:00' as dt, 222 as val
union
select '2013-02-21 14:30' as dt, 333 as val
)
select DATEPART(hh, DATEADD(mi, -1, dt)) +1, SUM(val) from cte -- Вычитаем минуту, чтобы час попал в предыдущий отчетный
group by DATEPART(hh, DATEADD(mi, -1, dt))+1

Благодарю за идею, складывает как задумывалось, но прошу прощения я оказывается не до конца раскрыл проблему.... он получается складывает все часы за любые дни, т.е.
Дата Значение
2013-02-21 13:30 111
2013-02-21 14:00 222
2013-02-22 13:30 444
2013-02-22 14:00 222

то итог выходит такой
Дата Значение
14:00 999

а результат хотелось бы получить такой, чтобы разграничение было на каждый день
Дата Значение
2013-02-21 14:00 333
2013-02-22 14:00 666