Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle SQL在不同组中的领先优势滞后_Sql_Oracle_Window Functions_Gaps And Islands - Fatal编程技术网

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 3 abx a b c 3 abc 预期结果集: KEY OPERATION DAY abc ADD 1 abe ADD 2 aby ADD

假设我有下表。它们的键是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   3   abx
a   b   c   3   abc
预期结果集:

KEY OPERATION DAY

abc  ADD      1
abe  ADD      2
aby  ADD      2
abc  REMOVE   2
abx  ADD      3
abc  ADD      3
abe  REMOVE   3
aby  REMOVE   3
如果一天不是连续的呢。例如:

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
预期结果是:

KEY OPERATION DAY

abc  ADD      1
abe  ADD      2
aby  ADD      2
abc  REMOVE   2
abx  ADD      5
abc  ADD      5
abe  REMOVE   5
aby  REMOVE   5
这里有一种使用滞后和超前的方法。其思想是比较每个键的上一个和下一个日期值,并使用该值来标识添加或删除键的日期-这假设该日期是一个连续递增的数字,没有间隔

with cte as (
    select
        t.*,
        lag(day) over(partition by p1, p2, p3 order by day) lag_day,
        lead(day) over(partition by p1, p2, p3 order by day) lead_day
    from mytable t
)
select p1, p2, p3, day, 'add' event
from cte
where lag_day is null or lag_day <> day - 1 
union all
select p1, p2, p3, day + 1, 'remove'
from cte
where lead_day is null or lead_day <> day + 1 
order by day, p1, p2, p3
使用中的示例数据,这将生成:

P1 | P2 | P3 | DAY | EVENT :- | :- | :- | --: | :----- a | b | c | 1 | add a | b | c | 2 | remove a | b | e | 2 | add a | b | y | 2 | add a | b | c | 3 | add a | b | e | 3 | remove a | b | x | 3 | add a | b | y | 3 | remove a | b | c | 4 | remove a | b | x | 4 | remove 这似乎比您预期的结果更完整。请注意,在最后一天仍然可用的所有记录在下一假设日期显示为已删除-这似乎与所有新记录在第一天显示为已添加的事实一致

我没有使用伪键,因为它看不出它有什么帮助——而且,如果值有多个字符,它可能会因为创建假重复而导致麻烦。

这里有一种使用滞后和超前的方法。其思想是比较每个键的上一个和下一个日期值,并使用该值来标识添加或删除键的日期-这假设该日期是一个连续递增的数字,没有间隔

with cte as (
    select
        t.*,
        lag(day) over(partition by p1, p2, p3 order by day) lag_day,
        lead(day) over(partition by p1, p2, p3 order by day) lead_day
    from mytable t
)
select p1, p2, p3, day, 'add' event
from cte
where lag_day is null or lag_day <> day - 1 
union all
select p1, p2, p3, day + 1, 'remove'
from cte
where lead_day is null or lead_day <> day + 1 
order by day, p1, p2, p3
使用中的示例数据,这将生成:

P1 | P2 | P3 | DAY | EVENT :- | :- | :- | --: | :----- a | b | c | 1 | add a | b | c | 2 | remove a | b | e | 2 | add a | b | y | 2 | add a | b | c | 3 | add a | b | e | 3 | remove a | b | x | 3 | add a | b | y | 3 | remove a | b | c | 4 | remove a | b | x | 4 | remove 这似乎比您预期的结果更完整。请注意,在最后一天仍然可用的所有记录在下一假设日期显示为已删除-这似乎与所有新记录在第一天显示为已添加的事实一致


我没有使用伪键,因为它看不出它有什么帮助——而且,如果值有多个字符,它可能会因为创建虚假的重复而导致麻烦。

如果需要,您可以在不使用窗口函数的情况下执行此操作:

select key, 'add', day
from t
where not exists (select 1
                  from t t2
                  where t2.key = t.key and t2.day = t.day - 1
                 )
union all
select key, 'remove', day + 1
from t
where not exists (select 1
                  from t t2
                  where t2.key = t.key and t2.day = t.day + 1
                 )

如果需要,可以在不使用窗口功能的情况下执行此操作:

select key, 'add', day
from t
where not exists (select 1
                  from t t2
                  where t2.key = t.key and t2.day = t.day - 1
                 )
union all
select key, 'remove', day + 1
from t
where not exists (select 1
                  from t t2
                  where t2.key = t.key and t2.day = t.day + 1
                 )

我觉得这太棒了。事实上,这两天之间是有间隔的。我在想,是否需要先排名几天,然后在排名上领先一圈?例如,第二天可以有多个带有不同键的时间戳。我认为这太棒了。事实上,这两天之间是有间隔的。我在想,是否需要先排名几天,然后在排名上领先一圈?例如,第2天可以有多个带有不同键的时间戳。