我有一些记录一些顺序处理事件的数据。
每个事件都在一个位置(Location)发生,并且包括开始日期(BeginDT)和结束日期(EndDT)。
在某个位置进行处理可能涉及多个顺序步骤,每个步骤都使用BeginDT和EndDT记录。
在某个位置未完成的步骤应记录为已完成(完整为(1))。
该位置的最后一步应记录为不完整(完整为false(0))。
但是,由于某些丢失或错误的记录,可能导致某个位置的处理不完整。 当在某个位置进行的处理具有一个或多个指示未完成但没有后续最终步骤指示完成的步骤时,则将不完整记录(或该位置上序列的最新不完整记录)视为最终记录
可能会在同一位置依次处理多次。 如果在同一位置按顺序处理多次,并且该位置的前导事件已完成,则每个事件都被认为是完全独立的。
我提供了一种方法,试图通过标识上一条和下一条记录来帮助确定如何处理每个事件,但是我不确定这是否有用。
对于位置处的每个顺序处理事件集,所需的最终结果是顺序,位置,最早的BeginDT和最新的EndDT:
/*
[Order] Location BeginDT EndDT
1 A 2000-01-01 2000-01-06
2 B 2000-01-10 2000-01-11
3 C 2000-01-20 2000-01-21
4 D 2000-01-30 2000-01-31
5 A 2000-02-01 2000-02-02
6 C 2000-02-10 2000-02-11
7 C 2000-02-20 2000-02-21
8 B 2000-03-01 2000-03-02
9 D 2000-03-10 2000-03-11
10 D 2000-03-20 2000-03-23
11 E 2000-03-30 2000-03-31
*/
declare @T table (
ID int identity,
Location varchar(20),
Complete bit,
BeginDT date,
EndDT date
);
insert @T (Location, Complete, BeginDT, EndDT)
values
('A', 0, '2000-01-01', '2000-01-02'),
('A', 0, '2000-01-03', '2000-01-04'),
('A', 1, '2000-01-05', '2000-01-06'),
('B', 1, '2000-01-10', '2000-01-11'),
('C', 1, '2000-01-20', '2000-01-21'),
('D', 0, '2000-01-30', '2000-01-31'),
('A', 1, '2000-02-01', '2000-02-02'),
('C', 1, '2000-02-10', '2000-02-11'),
('C', 1, '2000-02-20', '2000-02-21'),
('B', 1, '2000-03-01', '2000-03-02'),
('D', 1, '2000-03-10', '2000-03-11'),
('D', 0, '2000-03-20', '2000-03-21'),
('D', 1, '2000-03-22', '2000-03-23'),
('E', 1, '2000-03-30', '2000-03-31');
with cte as (
select
row_number() over (order by BeginDT) as [Order],
Location,
Complete,
BeginDT,
EndDT
from @T
)
select
*
from cte
order by
[Order],
Complete;
with cte as (
select
row_number() over (order by BeginDT) as [Order],
Location,
Complete,
BeginDT,
EndDT
from @T
)
select
[Order],
Location,
BeginDT,
EndDT,
Complete,
max(Previous) as Previous,
max(cast(PreviousComplete as int)) as PreviousComplete,
max([Next]) as [Next]
from (
select
cte.[Order],
cte.Location,
cte.BeginDT,
cte.EndDT,
cte.Complete,
case
when cte.[Order] = j.[Order] + 1
then j.Location
else NULL
end as Previous,
case
when cte.[Order] = j.[Order] + 1
then j.Complete
else NULL
end as PreviousComplete,
case
when cte.[Order] = j.[Order] - 1
then j.Location
else NULL
end as [Next]
from cte
cross join (
select
[Order],
Location,
Complete
from cte
) as j
) as S
group by
[Order],
Location,
BeginDT,
EndDT,
Complete;
我开发了一个解决方案:
with
cte1 as (
select
row_number() over (order by BeginDT, EndDT) as [Order],
Location,
IsComplete,
BeginDT,
EndDT
from @T
),
cte2 as (
select
[Order],
Location,
case
when 1 <> 1
or Location <> Previous
or Previous is NULL
or (
1 = 1
and Location = Previous
and PreviousIsComplete = 1
)
then BeginDT
end as BeginDT,
case
when 1 <> 1
or IsComplete = 1
or (
IsComplete = 0
and (
1 <> 1
or Location <> [Next]
or [Next] is NULL
)
)
then EndDT
end as EndDT
from (
select
[Order],
Location,
BeginDT,
EndDT,
IsComplete,
max(Previous) as Previous,
max(cast(PreviousIsComplete as int)) as PreviousIsComplete,
max([Next]) as [Next]
from (
select
cte1.[Order],
cte1.Location,
cte1.BeginDT,
cte1.EndDT,
cte1.IsComplete,
case
when cte1.[Order] = cj1.[Order] + 1
then cj1.Location
else NULL
end as Previous,
case
when cte1.[Order] = cj1.[Order] + 1
then cj1.IsComplete
else NULL
end as PreviousIsComplete,
case
when cte1.[Order] = cj1.[Order] - 1
then cj1.Location
else NULL
end as [Next]
from cte1
cross join (
select
[Order],
Location,
IsComplete
from cte1
) as cj1
) as T1
group by
[Order],
Location,
BeginDT,
EndDT,
IsComplete
) as T2
),
cte3 as (
select
'Begin' as [Type],
row_number() over (order by [Order]) as [Order],
Location,
min(BeginDT) as DT
from cte2
where BeginDT is not NULL
group by
[Order],
Location
union
select
'End' as [Type],
row_number() over (order by [Order]) as [Order],
Location,
min(EndDT) as DT
from cte2
where EndDT is not NULL
group by
[Order],
Location
)
select
[Order],
Location,
[Begin] as BeginDT,
[End] as EndDT
from (
select
[Type],
[Order],
Location,
DT
from cte3
) as T
pivot (
max(DT) for [Type] in ([Begin], [End])
) as pT
order by [Order];
我欢迎任何改进。谢谢。