按组计算日期时间的时间
Calculating time with datetime by groups
我有两个 table 票和任务。注册票证后,它会出现在票证 table 中,并且使用票证进行的每个操作都会保存在任务 table 中。工单 table 包括工单创建者、开始和结束日期(如果已关闭)等信息。任务 table 如下所示:
ID Ticket_ID Task_type_ID Task_type Group_ID Submit_Date
1 120 1 Opened 3 2016-12-09 11:10:22.000
2 120 2 Assign 4 2016-12-09 12:10:22.000
3 120 3 Paused 4 2016-12-09 12:30:22.000
4 120 4 Unpause 4 2016-12-10 10:30:22.000
5 120 2 Assign 6 2016-12-12 10:30:22.000
6 120 2 Assign 7 2016-12-12 15:30:22.000
7 120 5 Modify NULL 2016-12-13 15:30:22.000
8 120 6 Closed NULL 2016-12-13 16:30:22.000
我想计算每组完成任务的时间。开始时间是将工单分配给某个组的时间,结束时间是该组完成任务的时间(如果他们将其分配到其他地方或将其关闭)。但它不应包括暂停时间(task_type_ID 3 到 4)。此外,当工单分配给其他组时,新的组 ID 会出现在之前的 task/row 中。如果任务经过多个组,它应该计算票在每个组手中的时间。
我知道这很复杂,但也许有人有想法可以让我开始构建。
这是一个相当复杂的间隙和孤岛问题。
这是一种方法:
select distinct
ticket_id,
group_id,
sum(sum(datediff(minute, submit_date, lead_submit_date)))
over(partition by group_id) elapsed_minutes
from (
select
t.*,
row_number() over(partition by ticket_id order by submit_date) rn1,
row_number() over(partition by ticket_id, group_id order by submit_date) rn2,
lead(submit_date) over(partition by ticket_id order by submit_date) lead_submit_date
from mytable t
) t
where task_type <> 'Paused' and group_id is not null
group by ticket_id, group_id, rn1 - rn2
在子查询中,我们将行号分配给两个不同分区内的记录(by tickets vs by ticket and 组),并恢复 的日期接下来记录lead()
。
然后我们可以使用行号之间的差异来构建 "adjacent" 记录组(工单在同一组中),同时不考虑工单暂停的时间段。聚合在这里发挥作用。
最后一步是计算在每个组中花费的总时间:这处理票证在其生命周期内多次分配给同一组的情况(尽管您的样本数据中没有显示,描述这个问题听起来像是可能会发生)。我们可以用另一层聚合来做到这一点,但我选择了 window 总和和 distinct
,这避免了在查询中再添加一层嵌套。
独立执行子查询可能有助于更好地理解逻辑(参见下面的数据库fiddle)。
对于您的示例数据,the query yields:
ticket_id | group_id | minutes_elapsed
--------: | -------: | --------------:
120 | 3 | 60
120 | 4 | 2900
120 | 6 | 300
120 | 7 | 1440
其实我觉得这很简单。只需使用 lead()
获取下一个提交时间值并按工单和组进行聚合,忽略暂停:
select ticket_id, group_id, sum(dur_sec)
from (select t.*,
datediff(second, submit_date, lead(submit_date) over (partition by ticket_id order by submit_date)) as dur_sec
from mytable t
) t
where task_type <> 'Paused' and group_id is not null
group by ticket_id, group_id;
Here 是一个 db<>fiddle(感谢 GMB 创建了原始 fiddle)。
我有两个 table 票和任务。注册票证后,它会出现在票证 table 中,并且使用票证进行的每个操作都会保存在任务 table 中。工单 table 包括工单创建者、开始和结束日期(如果已关闭)等信息。任务 table 如下所示:
ID Ticket_ID Task_type_ID Task_type Group_ID Submit_Date
1 120 1 Opened 3 2016-12-09 11:10:22.000
2 120 2 Assign 4 2016-12-09 12:10:22.000
3 120 3 Paused 4 2016-12-09 12:30:22.000
4 120 4 Unpause 4 2016-12-10 10:30:22.000
5 120 2 Assign 6 2016-12-12 10:30:22.000
6 120 2 Assign 7 2016-12-12 15:30:22.000
7 120 5 Modify NULL 2016-12-13 15:30:22.000
8 120 6 Closed NULL 2016-12-13 16:30:22.000
我想计算每组完成任务的时间。开始时间是将工单分配给某个组的时间,结束时间是该组完成任务的时间(如果他们将其分配到其他地方或将其关闭)。但它不应包括暂停时间(task_type_ID 3 到 4)。此外,当工单分配给其他组时,新的组 ID 会出现在之前的 task/row 中。如果任务经过多个组,它应该计算票在每个组手中的时间。 我知道这很复杂,但也许有人有想法可以让我开始构建。
这是一个相当复杂的间隙和孤岛问题。
这是一种方法:
select distinct
ticket_id,
group_id,
sum(sum(datediff(minute, submit_date, lead_submit_date)))
over(partition by group_id) elapsed_minutes
from (
select
t.*,
row_number() over(partition by ticket_id order by submit_date) rn1,
row_number() over(partition by ticket_id, group_id order by submit_date) rn2,
lead(submit_date) over(partition by ticket_id order by submit_date) lead_submit_date
from mytable t
) t
where task_type <> 'Paused' and group_id is not null
group by ticket_id, group_id, rn1 - rn2
在子查询中,我们将行号分配给两个不同分区内的记录(by tickets vs by ticket and 组),并恢复 的日期接下来记录lead()
。
然后我们可以使用行号之间的差异来构建 "adjacent" 记录组(工单在同一组中),同时不考虑工单暂停的时间段。聚合在这里发挥作用。
最后一步是计算在每个组中花费的总时间:这处理票证在其生命周期内多次分配给同一组的情况(尽管您的样本数据中没有显示,描述这个问题听起来像是可能会发生)。我们可以用另一层聚合来做到这一点,但我选择了 window 总和和 distinct
,这避免了在查询中再添加一层嵌套。
独立执行子查询可能有助于更好地理解逻辑(参见下面的数据库fiddle)。
对于您的示例数据,the query yields:
ticket_id | group_id | minutes_elapsed --------: | -------: | --------------: 120 | 3 | 60 120 | 4 | 2900 120 | 6 | 300 120 | 7 | 1440
其实我觉得这很简单。只需使用 lead()
获取下一个提交时间值并按工单和组进行聚合,忽略暂停:
select ticket_id, group_id, sum(dur_sec)
from (select t.*,
datediff(second, submit_date, lead(submit_date) over (partition by ticket_id order by submit_date)) as dur_sec
from mytable t
) t
where task_type <> 'Paused' and group_id is not null
group by ticket_id, group_id;
Here 是一个 db<>fiddle(感谢 GMB 创建了原始 fiddle)。