Создание последовательных диапазонов дат для элементов в очереди - PullRequest
0 голосов
/ 04 апреля 2019

У меня есть таблица 'item_queue', содержащая элементы, группы и порядковый номер.Каждый элемент уникален и удерживается в группе с номером, указывающим последовательность.Общее количество для этого элемента, например,

group_id|item_id|sequence_order_number|count
--------------------------------------------
A       |123    |1                    |20
A       |124    |2                    |30
B       |125    |1                    |10

Учитывая эту информацию, я пытаюсь установить последовательные даты начала и окончания

Дата и время начала первого элемента для группытекущее время, например, предположим, что начало элемента 123 - «2019-04-04 12: 00: 00.000», тогда конечное время-время будет началом + (количество * минут), поэтому «2019-04-04 12: 20: 00.000»

Начало элемента 124 будет равно этой конечной дате, поскольку она является следующей в последовательности для этой группы.затем вычисляется конец таким же образом, чтобы быть '2019-04-04 12: 50: 00.000'

пункт 125 снова начал бы время с '2019-04-04 12: 00: 00.000', так какя в другой группе

Я попытался сделать это несколькими способами, и я думаю, что ответ - рекурсивный cte , но я не могу обернуть его вокруг, чтобы сделать эторабота для одной или нескольких групп, моя неудачная попытка для одной группы:

;with cte as
(
    select
        group_id,
        item_id,
        count,
        GETDATE() as start_datetime,
        DATEADD(MINUTE, count, GETDATE()) as end_datetime,
        iq.sequence_order_number
    from item_queue iq
    where iq.group_id = 'A'
    union all
    select
        group_id,
        item_id,
        count,
        cte.end_datetime,
        DATEADD(MINUTE, count, cte2.end_datetime) as end_datetime,
        iq.sequence_order_number
    from item_queue iq
    inner join cte
        on cte.group_id = iq.group_id
        and cte.sequence_order_number > iq.sequence_order_number
    where iq.group_id = 'A'
)
select * from cte

Я подозреваю, что ответ может включать окно номера строки, например,

ROW_NUMBER() OVER (Partition By iq.group_id Order By iq.sequence_order_number ASC)

Но у меня возникли проблемыиспользовать его рекурсивно.

Использование SQL Server 2012, без возможности обновления этой базы данных.

1 Ответ

0 голосов
/ 04 апреля 2019

Минуты, которые вы хотите добавить, являются практически накопительной суммой. Функция окна sum() over() доступна в 2012 году и выполняет именно это. Попробуйте:

select 
    *,
    isnull(sum([count]) over 
                            ( 
                                partition by group_id 
                                order by item_id asc  
                                rows between unbounded PRECEDING   and 1 PRECEDING  
                            )
    ,0) as cum_count_start,
    sum([count]) over ( partition by group_id order by item_id asc  ) as cum_count_end
    from item_queue

Вы уже знаете, как использовать dateadd после этой точки.

Что делают отдельные функции оконной функции:

partition by group_id: Разделить (разделить) вычисления для каждого подмножества значения group_id

order by item_id asc: выполнить виртуальную сортировку строк, к которым будет применен диапазон окна

rows between....: фактическое окно. Что касается даты начала, мы хотим рассмотреть все строки от начала (таким образом, неограниченная предшествующая) до предыдущей (таким образом, 1 предшествующая), так как вы не хотите, чтобы начальная дата включала текущую строку [count]. Обратите внимание, что пропуск этого предложения, как мы делали на cum_count_end, эквивалентен rows between unbounded preceding and current row.

isnull (..., 0) необходим, потому что для первой строки каждого group_id вы хотите добавить 0 к дате начала, но оконная функция не видит строк и возвращает NULL, поэтому нам нужно изменить это на 0.

...