为队列中的项目创建顺序日期范围

Creating sequential date ranges for items in a queue

我有一个 table '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' 那么 结束日期时间将是 start + (count * minutes) 所以 '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

我怀疑答案可能涉及行号 window 之类的

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

但我在递归使用它时遇到了问题。

使用 SQL 服务器 2012,无法升级此数据库。

您要添加的分钟数实际上是累加的总和。 sum() over() window 函数在 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 了。

个别 window 函数调用的作用:

partition by group_id :分离(分区)每个 group_id 值子集的计算

order by item_id asc :对将应用 window 范围的行进行虚拟排序

rows between....:实际的window。对于开始日期,我们要考虑从开始(因此前面无界)到前一行(因此前面 1)的所有行,因为您不希望开始日期包括当前行的 [count]。请注意,像我们在 cum_count_end 上所做的那样省略此子句等同于 rows between unbounded preceding and current row.

isnull(...,0) 是必需的,因为对于每个 group_id 的第一行,您想要将 0 添加到开始日期,但是 window 函数看不到任何行和returns NULL,因此我们需要将其更改为 0。