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

时间:2019-04-04 12:01:53

标签: sql-server tsql sql-server-2012 common-table-expression

我有一个表“ 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 :(得分:0)

您要添加的分钟实际上是一个累加的总和。 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....:实际窗口。对于开始日期,由于您不希望开始日期包括当前行的[count],因此我们要考虑从开始(因此前无界)到上一个(因此前1)的所有行。请注意,像在cum_count_end上所做的那样省略此子句等效于rows between unbounded preceding and current row

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