Oracle SQL在整个组中领先滞后于历史数据

Oracle SQL在整个组中领先滞后于历史数据,sql,oracle,window-functions,gaps-and-islands,Sql,Oracle,Window Functions,Gaps And Islands,我问了一个类似的问题。假设我有下表结构。P1、P2、P3这三个属性表示为一个键。我想每天比较每把钥匙。例如,从第1天到第2天,删除abc并添加abe、aby P1 P2 P3 DAY KEY a b c 1 abc a b e 2 abe a b y 2 aby a b x 5 abx a b c 5 abc 我正在考虑生成一个结果集,该结果集具有跟踪历史的开始/结束日期。预期结果集: P1

我问了一个类似的问题。假设我有下表结构。P1、P2、P3这三个属性表示为一个键。我想每天比较每把钥匙。例如,从第1天到第2天,删除abc并添加abe、aby

P1  P2  P3  DAY  KEY

a   b   c   1    abc
a   b   e   2    abe
a   b   y   2    aby
a   b   x   5    abx
a   b   c   5    abc
我正在考虑生成一个结果集,该结果集具有跟踪历史的开始/结束日期。预期结果集:

P1  P2  P3      KEY  STARTTIME  ENDTIME

a   b   c       abc     1         2
a   b   e       abe     2         5
a   b   y       aby     2         5
a   b   x       abx     5        NULL
a   b   c       abc     5        NULL
谢谢你为我上一篇文章提供帮助。我修改了下面的一个答案,以获得添加/删除结果集,但仍然无法转换为上面的开始/结束时间模型

with base as (
select
    'a' as p1,
    'b' as p2,
    'c' as p3,
    1 as day
from dual
union
select
    'a' as p1,
    'b' as p2,
    'y' as p3,
    2 as day
from dual
union
select
    'a' as p1,
    'b' as p2,
    'e' as p3,
    2 as day
from dual
union
select
    'a' as p1,
    'b' as p2,
    'x' as p3,
    5 as day
from dual
union
select
    'a' as p1,
    'b' as p2,
    'c' as p3,
    5 as day
from dual
),
calendar as (
select
    day,
    lead(day) over (order by day asc) as nextday,
    lag(day) over (order by day asc) as prevday
from
    (select distinct day from base)
),
data as (
    select
        p1,
        p2,
        p3,
        base.day,
        lead(base.day) over (partition by p1, p2, p3 order by base.day asc) as nextrow,
        lag(base.day) over (partition by p1, p2, p3 order by base.day asc) as prevrow,
        calendar.nextday,
        calendar.prevday
    from 
        base
    left join
        calendar
            on calendar.day = base.day
)
select * from data
/

select
    d1.p1,
    d1.p2,
    d1.p3,
    d1.day,
    d1.nextrow,
    d1.prevrow,
    'ADD' as op,
    d1.day as d
from 
    data d1
where
    prevrow is null or prevrow <> prevday
union
select
    d2.p1,
    d2.p2,
    d2.p3,
    d2.day,
    d2.nextrow,
    d2.prevrow,
    'REMOVE' as op,
    nextday
from 
    data d2
where
    nextrow is null or nextrow <> nextday
order by
    d, op asc

我认为这是一个缺口和孤岛问题。您可以使用行号之间的差异来标识相邻记录的组。要计算结束日,需要更多的逻辑,因为日期不是连续的:我使用了一个窗口和,当日期和第一个值发生变化时,它会增加,以获得实际的下一个日期:

select 
    p1, 
    p2,
    p3,
    min(day) over(partition by p1, p2, p3, rn1 - rn2 order by day) start_day,
    case 
        when min(day) over(partition by p1, p2, p3, rn1 - rn2 order by day) 
            <> max(lead_day) over()
        then max(lead_day) over(partition by day_grp) 
    end end_day
from (
    select 
        t.*,
        sum(case when day = lead_day then 0 else 1 end) over(order by day) day_grp
    from (
    select
        t.*,
        row_number() over(order by day) rn1,
        row_number() over(partition by p1, p2, p3 order by day) rn2,
        lead(day) over(order by day) lead_day
    from mytable t
    ) t
) t
:


我认为这是一个缺口和孤岛问题。您可以使用行号之间的差异来标识相邻记录的组。要计算结束日,需要更多的逻辑,因为日期不是连续的:我使用了一个窗口和,当日期和第一个值发生变化时,它会增加,以获得实际的下一个日期:

select 
    p1, 
    p2,
    p3,
    min(day) over(partition by p1, p2, p3, rn1 - rn2 order by day) start_day,
    case 
        when min(day) over(partition by p1, p2, p3, rn1 - rn2 order by day) 
            <> max(lead_day) over()
        then max(lead_day) over(partition by day_grp) 
    end end_day
from (
    select 
        t.*,
        sum(case when day = lead_day then 0 else 1 end) over(order by day) day_grp
    from (
    select
        t.*,
        row_number() over(order by day) rn1,
        row_number() over(partition by p1, p2, p3 order by day) rn2,
        lead(day) over(order by day) lead_day
    from mytable t
    ) t
) t
:


关键栏目的重点是什么?如果它只是P1、P2、P3的串联,那么就别管它;即使你认为你需要它,你也不需要它,它最终会给你带来麻烦;这不意味着他们都在第2天或更早的时候结束了吗?若否,原因为何?我在你的帖子中没有看到对此的解释。关键专栏的重点是什么?如果它只是P1、P2、P3的串联,那么就别管它;即使你认为你需要它,你也不需要它,它最终会给你带来麻烦;这不意味着他们都在第2天或更早的时候结束了吗?若否,原因为何?我在你的帖子中没有看到对此的解释。