【问题标题】:aggregate date ranges with gaps in oracle在 oracle 中有间隙的聚合日期范围
【发布时间】:2019-07-29 07:14:43
【问题描述】:

我需要汇总允许每个 ID 之间最多 2 天间隔的日期范围。任何帮助将不胜感激

create table tt ( id int, startdate date, stopdate date);  
Insert into TT values (1,'24/05/2010', '29/05/2010');
Insert into TT values (1,'30/05/2010', '22/06/2010');
Insert into TT values (10,'26/06/2012', '28/06/2012');
Insert into TT values (10,'29/06/2012', '30/06/2012');
Insert into TT values (10,'01/07/2012', '30/07/2012');
Insert into TT values (10,'03/08/2012', '30/12/2012');
insert into TT values (90,'08/03/2002', '16/03/2002');
insert into TT values (90,'31/01/2002', '15/02/2002');
insert into TT values (90,'15/02/2002', '28/02/2002');
insert into TT values (90,'31/01/2002', '15/02/2004');
insert into TT values (90,'15/02/2004', '15/04/2004');
insert into TT values (90,'01/03/2002', '07/03/2002');

预期的输出是:

1     24/05/2010    22/06/2010
10    26/06/2012    30/07/2012
10    03/08/2012    30/12/2012 
90    31/01/2002    15/04/2004

【问题讨论】:

  • 您能否将预期结果也添加到问题中。 ?

标签: oracle date range aggregate


【解决方案1】:

如果您使用的是 12c,则可以使用我最喜欢的 SQL 功能之一:模式匹配 (match_recognize)。

有了这个,你需要定义一个模式变量。在这里,您将检查当前行的开始日期是否在前一行的停止日期的两天内。即:

startdate <= prev ( stopdate ) + 2

您要搜索的模式是任意行,后跟零个或多个符合此条件的行。

所以你有一个“总是正确的”strt 变量,后跟 *(正则表达式零个或多个量词)出现的 within2 变量:

( strt within2* ) 

我猜您还需要按 ID 划分范围。所以我为此添加了一个分区。

把它们放在一起,你会得到:

select * 
from   tt match_recognize (
  partition by id
  order by startdate, stopdate
  measures
    first ( startdate ) startdate, 
    last ( stopdate ) stopdate
  pattern ( strt within2* ) 
  define 
    within2 as startdate <= prev ( stopdate ) + 2
);

ID   STARTDATE    STOPDATE     
   1 24/05/2010   22/06/2010   
  10 26/06/2012   30/07/2012   
  10 03/08/2012   30/12/2012  

如果你想了解更多,可以找several match_recognize examples here

【讨论】:

  • 但是,这不适用于以下子集,其中 stopdate = startdate = null,请参见示例:create table tt (id VARCHAR(8), startdate date, stopdate date);insert into TT values ('ALH002','01/09/2010 00:00', '21/02/2011 00:00');insert into TT values ('ALH002','21/02/2011 00:00', '06/06/2011 00:00');insert into TT values ('ALH002','06/06/2011 00:00', ''); 它应该导致以下行:@ 987654330@
  • 这只是更新 measure 子句中的 stopdate 以返回您想要的值的问题; max ( stopdate )last (nvl ( stop, start ))
  • 谢谢!这将解决这个特殊问题。但是,对于另一行中包含的范围,脚本将产生不正确的输出。我已经更新了上面的查询
  • 我不确定这里的问题是什么。使用您添加到问题中的值运行答案会得到您请求的输出。
  • 我的错误,我更正了输入数据以反映前面描述的问题
猜你喜欢
  • 2013-11-19
  • 1970-01-01
  • 1970-01-01
  • 2018-09-02
  • 1970-01-01
  • 2014-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多