问题描述
我有一个表,该表列出了事件,事件中的操作以及每个操作的时间。事件ID不是唯一的,因为它是同一事件,只是发生在不同的时间。对于相同类型的事件,操作可能有所不同。同一事件永远不会连续运行两次。
我想按照给定的示例填充三个新列。这将使我能够对单独的事件进行分析,因为我将能够生成唯一的“事件” ID。
编辑: 我已经尝试过基于事件的PARTITION函数,但由于sql Server假定两个事件(A和B)并因此为所有“ A”事件提供了相同的开始日期,所以它没有用,即使实际上我需要将它们显示为单独的具有不同开始日期的事件。
谢谢!
解决方法
这只是窗口功能:
select t.*,min(operationtime) over (partition by event) as event_start_time,max(operationtime) over (partition by event) as event_end_time,concat(event,'-',min(operationtime) over (partition by event)) as event_id
from t;
实际上,对于事件ID,您可能想要以下内容:
concat(event,convert(varchar(255),min(operationtime) over (partition by event),101)) as event_id
或您想要的日期的任何格式。我建议使用YYYY-MM-DD作为日期格式。
,此方法显式创建事件组,然后使用窗口查询与其他答案非常相似。我创建了一个简单的示例表来显示结果。
数据
drop table if exists #tTEST;
go
select * INTO #tTEST from (values
('A','X','2020-01-08'),('A','Z','2020-02-08'),('B','2020-03-08'),'2020-04-08'),'2020-05-08'),'2020-06-08')) V([Event],[Operation],operation_time);
查询
;with
grp_cte as (
select t.*,case when lag([Event],1,0) over (order by operation_time) != [Event] then 1 else 0 end grp_ind
from #tTEST t),event_grp_cte as (
select gc.*,sum(grp_ind) over (order by operation_time) EventGroup
from grp_cte gc)
select
t.*,min(operation_time) over(partition by EventGroup) event_start_time,max(operation_time) over(partition by EventGroup) event_end_time,min(operation_time) over(partition by EventGroup)) event_id
from event_grp_cte t
order by operation_time;
结果
Event Operation operation_time grp_ind EventGroup rn1 rn2 event_start_time event_end_time event_id
A X 2020-01-08 1 1 1 1 2020-01-08 2020-02-08 A-2020-01-08
A Z 2020-02-08 0 1 2 2 2020-01-08 2020-02-08 A-2020-01-08
B X 2020-03-08 1 2 3 1 2020-03-08 2020-04-08 B-2020-03-08
B Z 2020-04-08 0 2 4 2 2020-03-08 2020-04-08 B-2020-03-08
A X 2020-05-08 1 3 5 3 2020-05-08 2020-06-08 A-2020-05-08
A Z 2020-06-08 0 3 6 4 2020-05-08 2020-06-08 A-2020-05-08
,
我理解这是一个“孤岛”问题,您想在其中建立连续的日常事件组。
一个选项使用行号之间的差异来标识组:
select
t.*,min(operation_time) over(partition by event,rn1 - rn2) event_start_time,max(operation_time) over(partition by event,rn1 - rn2) event_end_time,rn1 - rn2)) event_id
from (
select
t.*,row_number() over(order by operation_time) rn1,row_number() over(partition by event order by operation_time) rn2
from mytable t
) t
order by operation_time
如果每天总是只有一个事件(如示例数据所示),那么一个row_number()
就足够了,以及日期运算:
select
t.*,grp) event_start_time,grp) event_end_time,grp)) event_id
from (
select
t.*,dateadd(
day,- row_number() over(partition by event order by operation_time),operation_time
) grp
from mytable t
) t