Кто-нибудь знает простой метод решения этой проблемы?
У меня есть таблица, которая состоит из времени начала событий и связанной с ними продолжительности. Мне нужно иметь возможность разбить продолжительность событий на 30-минутные интервалы. Так, например, если событие начинается в 10:45:00 и его продолжительность составляет 00:17:00, то возвращаемый набор должен выделить 15 минут на интервал 10:30:00 и 00:02:00 минут на 11:00. : 00 интервал.
Я уверен, что смогу придумать неуклюжий подход, но хотелось бы чего-нибудь попроще. Думаю, это должно происходить довольно часто, но сегодня Google бесполезен.
Спасибо,
Стив





Вы можете создать таблицу поиска с указанием только времени (более 24 часов) и присоединиться к этой таблице. Вам нужно будет изменить дату на ту, которая использовалась в поиске. Затем выполните датировку верхнего и нижнего интервалов, чтобы определить их продолжительность. Каждый средний интервал составляет 30 минут.
create table #interval_lookup (
from_date datetime,
to_date datetime
)
declare @time datetime
set @time = '00:00:00'
while @time < '2 Jan 1900'
begin
insert into #interval_lookup values (@time, dateadd(minute, 30, @time))
set @time = dateadd(minute, 30, @time)
end
declare @search_from datetime
declare @search_to datetime
set @search_from = '10:45:00'
set @search_to = dateadd(minute, 17, @search_from)
select
from_date as interval,
case
when from_date <= @search_from and
@search_from < to_date and
from_date <= @search_to and
@search_to < to_date
then datediff(minute, @search_from, @search_to)
when from_date <= @search_from and
@search_from < to_date
then datediff(minute, @search_from, to_date)
when from_date <= @search_to and
@search_to < to_date then
datediff(minute, from_date, @search_to)
else 30
end as duration
from
#interval_lookup
where
to_date > @search_from
and from_date <= @search_to
ALTER FUNCTION dbo.TVF_TimeRange_Split_To_Grid
(
@eventStartTime datetime
, @eventDurationMins float
, @intervalMins int
)
RETURNS @retTable table
(
intervalStartTime datetime
,intervalEndTime datetime
,eventDurationInIntervalMins float
)
AS
BEGIN
declare @eventMinuteOfDay int
set @eventMinuteOfDay = datepart(hour,@eventStartTime)*60+datepart(minute,@eventStartTime)
declare @intervalStartMinute int
set @intervalStartMinute = @eventMinuteOfDay - @eventMinuteOfDay % @intervalMins
declare @intervalStartTime datetime
set @intervalStartTime = dateadd(minute,@intervalStartMinute,cast(floor(cast(@eventStartTime as float)) as datetime))
declare @intervalEndTime datetime
set @intervalEndTime = dateadd(minute,@intervalMins,@intervalStartTime)
declare @eventDurationInIntervalMins float
while (@eventDurationMins>0)
begin
set @eventDurationInIntervalMins = cast(@intervalEndTime-@eventStartTime as float)*24*60
if @eventDurationMins<@eventDurationInIntervalMins
set @eventDurationInIntervalMins = @eventDurationMins
insert into @retTable
select @intervalStartTime,@intervalEndTime,@eventDurationInIntervalMins
set @eventDurationMins = @eventDurationMins - @eventDurationInIntervalMins
set @eventStartTime = @intervalEndTime
set @intervalStartTime = @intervalEndTime
set @intervalEndTime = dateadd(minute,@intervalMins,@intervalEndTime)
end
RETURN
END
GO
select getdate()
select * from dbo.TVF_TimeRange_Split_To_Grid(getdate(),23,30)
2008-10-31 11:28:12.377
intervalStartTime intervalEndTime eventDurationInIntervalMins
----------------------- ----------------------- ---------------------------
2008-10-31 11:00:00.000 2008-10-31 11:30:00.000 1,79372222222222
2008-10-31 11:30:00.000 2008-10-31 12:00:00.000 21,2062777777778
select input.eventName, result.* from
(
select
'first' as eventName
,cast('2008-10-03 10:45' as datetime) as startTime
,17 as durationMins
union all
select
'second' as eventName
,cast('2008-10-05 11:00' as datetime) as startTime
,17 as durationMins
union all
select
'third' as eventName
,cast('2008-10-05 12:00' as datetime) as startTime
,100 as durationMins
) input
cross apply dbo.TVF_TimeRange_Split_To_Grid(input.startTime,input.durationMins,30) result
eventName intervalStartTime intervalEndTime eventDurationInIntervalMins
--------- ----------------------- ----------------------- ---------------------------
first 2008-10-03 10:30:00.000 2008-10-03 11:00:00.000 15
first 2008-10-03 11:00:00.000 2008-10-03 11:30:00.000 2
second 2008-10-05 11:00:00.000 2008-10-05 11:30:00.000 17
third 2008-10-05 12:00:00.000 2008-10-05 12:30:00.000 30
third 2008-10-05 12:30:00.000 2008-10-05 13:00:00.000 30
third 2008-10-05 13:00:00.000 2008-10-05 13:30:00.000 30
third 2008-10-05 13:30:00.000 2008-10-05 14:00:00.000 10
(7 row(s) affected)
Мне просто пришлось отредактировать свою душу, так что это тоже выглядело немного некрасиво;). Раньше я неправильно истолковывал требования к вопросу. И я верю, что ваше решение будет работать намного быстрее.
Однако мой динамичный с точки зрения длины интервала;)
Мне очень нравится такой подход, он выглядит немного некрасиво. Интересно, каковы различия в производительности?