我问了类似的问题here。假设我有下面的表结构。 P1,P2,P3这三个属性代表一个键。我想比较每一天的每一把钥匙。例如,从第一天到第二天,删除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
我理解这是一个孤岛问题。您可以使用行号之间的差异来识别相邻记录的组。要计算end_day
,需要更多的逻辑,因为日期不是连续的:我使用了一个窗口sum()
,该窗口在日期更改时会增加,而first_value()
会获得实际的“下一个”日期:
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 | START_DAY | END_DAY:-| :-| :-| --------:| ------:一个| b | c | 1 | 2一个| b | e | 2 | 5一个| b | y | 2 | 5一个| b | x | 5 | null一个| b | c | 5 | null