这是一个使用 MATCH_RECOGNIZE 子句的有效解决方案,在 Oracle 版本 12.1 中引入。
WITH 子句模拟输入数据(它不是解决方案的一部分 - 删除它并在主查询中引用您的实际表和列名称)。
解决方案按 NM 分区,按 DT 排序,然后查找第三个日期比第一个日期晚 13 周以上的三个连续行。一旦它发现一个这样的事件,它就会用分区中所有剩余的行填充“匹配模式”,基本上把它们扔掉——因为我们只关心一个匹配。
注意我添加的两个 NM。 BB 确实有相隔超过 13 周的日期,但不在连续三个日期之内。 CC 有两个连续的日期已经相隔超过 13 周; CC 不在输出中,因为没有三个不同的日期开始。 (注意 - 这就是我阅读要求的方式;如果需要的是“相隔 13 周以上的连续日期也应该计算在内”,这可以很容易地解决 - 但这不是发帖人问题中的措辞。)
with
my_dates (nm, date_registered) as (
select 'A1', to_date('26/10/2019', 'dd/mm/yyyy') from dual union all
select 'A1', to_date( '2/11/2019', 'dd/mm/yyyy') from dual union all
select 'A1', to_date( '2/02/2020', 'dd/mm/yyyy') from dual union all
select 'A1', to_date( '9/02/2020', 'dd/mm/yyyy') from dual union all
select 'A1', to_date('16/02/2020', 'dd/mm/yyyy') from dual union all
select 'A1', to_date('23/02/2020', 'dd/mm/yyyy') from dual union all
select 'A1', to_date( '1/03/2020', 'dd/mm/yyyy') from dual union all
select 'A1', to_date( '8/03/2020', 'dd/mm/yyyy') from dual union all
select 'BB', to_date( '2/03/2019', 'dd/mm/yyyy') from dual union all
select 'BB', to_date('14/03/2019', 'dd/mm/yyyy') from dual union all
select 'BB', to_date('18/03/2019', 'dd/mm/yyyy') from dual union all
select 'BB', to_date('10/06/2019', 'dd/mm/yyyy') from dual union all
select 'BB', to_date( '3/04/2019', 'dd/mm/yyyy') from dual union all
select 'CC', to_date('15/08 2019', 'dd/mm/yyyy') from dual union all
select 'CC', to_date('15/02/2020', 'dd/mm/yyyy') from dual
)
-- end of sample data (for testing only); query begins below this comment
select nm
from my_dates
match_recognize(
partition by nm
order by date_registered
pattern ( a b c x* )
define c as date_registered > a.date_registered + 91
);
NM
----
A1
** 编辑 **
重新阅读问题,似乎只应考虑前三个日期(而不是任何三个连续的日期)。
这使问题更简单。并且解决方案可以轻松修改 - 唯一需要更改的是 pattern 子句,它应该变成:
pattern ( ^ a b c )
这会将搜索锚定在分区开头的三行。不检查其他行。