Разделение времени + длительности на интервалы в t-sql

Кто-нибудь знает простой метод решения этой проблемы?

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

Я уверен, что смогу придумать неуклюжий подход, но хотелось бы чего-нибудь попроще. Думаю, это должно происходить довольно часто, но сегодня Google бесполезен.

Спасибо,

Стив

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
6 354
2

Ответы 2

Вы можете создать таблицу поиска с указанием только времени (более 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

Создайте TVF, который разбивает одно событие:

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)

Мне очень нравится такой подход, он выглядит немного некрасиво. Интересно, каковы различия в производительности?

Ady 31.10.2008 11:48

Мне просто пришлось отредактировать свою душу, так что это тоже выглядело немного некрасиво;). Раньше я неправильно истолковывал требования к вопросу. И я верю, что ваше решение будет работать намного быстрее.

Bartek Szabat 31.10.2008 13:39

Однако мой динамичный с точки зрения длины интервала;)

Bartek Szabat 31.10.2008 13:49

Другие вопросы по теме