[英]Oracle SQL lead lag across different group
假设我有下表。 他们的关键就是 concat 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
这是一种使用lag()
和lead()
的方法。 这个想法是比较每个键的前一个和后一个日期值,并使用它来识别添加或删除键的日期 - 这假设day
是一个按顺序递增的数字,没有间隙。
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
使用此 db fiddle中的示例数据,这将产生:
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
这似乎比您的预期结果更完整。 请注意,在最后一个日期仍然可用的所有记录在下一个(假设的)日期显示为已删除 - 这似乎与所有新记录在第一天显示为添加的事实一致。
我没有使用伪键,因为它看不出它有什么帮助——而且,如果值有多个字符,它可能会通过创建“错误”重复项而导致麻烦。
如果需要,您可以在没有 window 函数的情况下执行此操作:
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
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.