在没有PL / SQL的情况下将行有效地分组为情节

时间:2019-05-24 05:36:34

标签: sql oracle plsql oracle12c gaps-and-islands

我有一个数据集,每个实体每天有一条记录。每天只有一种状态,但是一种状态可以在几天之内或仅在一天中出现

我要做的是将这些内容分为几集。因此,每当ID更改时,STATUS就会更改,或者下一条记录相隔一天以上,我想将其视为新的情节。

我一直在使用分析功能,但是虽然我可以按状态分组,但随后却不了解每几天的情况(尽管可能每个状态我可以一次通过它)

我也可以在PL / SQL中执行此操作,但是它在我的测试中非常慢。我希望有一种方法可以将它作为查询执行,或至少部分作为查询执行,以便pl / sql循环更快。

ID                      DAY         STATUS  Comment
E0000000000054245349    27-Feb-16   24      Start
E0000000000054245349    28-Feb-16   24  
E0000000000054245349    29-Feb-16   24  
E0000000000054245349    1-Mar-16    24  
E0000000000054245349    3-Mar-16    21      Gap & new status
E0000000000054245349    4-Mar-16    21  
            continuing daily
E0000000000054245349    12-Mar-16   21  
E0000000000054245349    13-Mar-16   21  
E0000000000054245349    14-Mar-16   21  
E0000000000054245349    15-Mar-16   40      No gap, but new status
E0000000000054245349    16-Mar-16   40  
E0000000000054245349    18-Mar-16   40      Gap, no new status
E0000000000054245349    19-Mar-16   40      
E0000000000054245349    1-Jan-17    21      Gap & new status
E0000000000054245349    2-Jan-17    21
E0000000000054245349    3-Jan-17    21      
E0000000000054245349    5-Jan-17    25      Gap, status and single day      

我理想的数据集想要这样的东西。奖励积分如果包含前后1天的记录的上一个/下一个状态,但如果需要的话,我总是可以通过后续查询来获取它们

ID                      START       END         STATUS
E0000000000054245349    27-Feb-16   1-Mar-16    24
E0000000000054245349    3-Mar-16    14-Mar-16   21
E0000000000054245349    15-Mar-16   16-Mar-16   40
E0000000000054245349    18-Mar-16   19-Mar-16   40
E0000000000054245349    1-Jan-17    3-Jan-17    21
E0000000000054245349    5-Jan-17    5-Jan-17    25      

2 个答案:

答案 0 :(得分:5)

您可以使用Tabibitosan Method轻松做到这一点:

select id, min(day) mnd, max(day) mxd, status
  from (
    select day - row_number() over (partition by id order by day) grp, id, day, status
      from t)
  group by id, grp, status
  order by id, grp;

dbfiddle demo

这将提供所需的输出。如果词组包含前/后1天的记录的上一个/下一个状态,我不会捕获该词组。在输出中,情节可能在一天之前/之后没有任何行。如果要从上一行/下一行获取状态,只需使用lag()lead ()。但是,如果您只想 ,如果新情节是由于状态变化而导致的,则有条件地使用分析功能:

select id, mnd, mxd, status, 
       case mnd when lag(mxd) over (partition by id order by mxd) + 1
                then lag(status) over (partition by id order by mxd) 
       end prev_status
  from (select id, min(day) mnd, max(day) mxd, status
          from (select day - row_number() over (partition by id order by day) grp, 
                       id, day, status
                  from t)
          group by id, grp, status)
  order by id, mnd;

...与lead()相同。

答案 1 :(得分:1)

这是一个空白和孤岛的问题-您可以按以下方式尝试

ffmpeg -i %04d.png animation.webp