订购事件,并在每个位置依次保留最早和最新的时间戳

时间:2018-07-17 23:34:32

标签: sql-server sql-server-2008 sql-server-2008-r2

我有一些记录一些顺序处理事件的数据。

每个事件都在一个位置(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];

我欢迎任何改进。谢谢。

0 个答案:

没有答案