为队列中的项目创建顺序日期范围
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。
我有一个 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。