sql-server - 对事件进行排序并按顺序在每个位置保留最早和最新的时间戳
问题描述
我有一些数据记录了一些顺序处理事件。
每个事件发生在一个位置 (Location) 并包括开始日期 (BeginDT) 和结束日期 (EndDT)。
一个位置的处理可能涉及多个连续步骤,每个步骤都用 BeginDT 和 EndDT 记录。
在某个位置的非最终步骤应记录为完成(完成为真 (1))。
在某个位置完成的步骤应记录为不完整(完整为假(0))。
但是,由于某些缺失或错误的记录,一个位置的处理可能会不完整。当一个位置的处理有一个(或多个)指示不完整的步骤(或多个步骤)但没有指示完成的后续最终步骤时,则不完整记录(或该位置序列的最近不完整记录)将被视为最终记录.
可能会在同一位置按顺序进行多次处理。当在同一位置按顺序处理多次并且该位置的主要事件已完成时,则每个事件都将被视为完全独立的。
我已经包含了一种方法,我试图使用该方法通过识别前一个和下一个记录来帮助确定如何处理每个事件,但我不确定这是否是一种有用的方法。
所需的最终结果是 Location 处每个顺序处理事件集的 Order、Location、最早的 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];
我欢迎任何改进。谢谢。
解决方案
推荐阅读
- c# - 使用 LAMBDA 在 C# LINQ 中自定义排序
- vb.net - 使用事件 ListView_ItemSelectionChanged 时消息框出现两次
- javascript - 通过 props 将解析的异步数据从父组件发送到子组件 - Vue
- dialogflow-es - 如何在谷歌对话流中添加多个链接建议卡
- oracle - 在 Oracle 中,如何获取已采样 X 年的唯一站点列表?
- runtime-error - SwiftUI Toggle 出现 kCFRunLoopCommonModes 错误
- ios - 按钮未完全绘制
- laravel - 函数 App\Http\Controllers\admin\ProductController::addToCart() 的参数太少,通过了 2 个,预期正好有 3 个
- android - 有没有办法在flutter firebase中创建具有特定文件名的文档
- c# - 如何使游戏对象的 transform.up 与向量相结合,而不改变它的 Y 旋转?