我有一个表“ 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,但无法升级此数据库。
答案 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。