提取满足某些时间间隔标准的时间点

Extract time points meeting some time interval criteria

我四处寻找,没有找到解决办法。 (有用的读物​​SQL to find time elapsed from multiple overlapping intervals

这是我的数据:规则是

"For each country, select the Date_ID in sequence with time interval equal or greater than 5 months"

我的工作环境是ORACLESQL。

非常感谢。

Country       Date_ID
----------------------
USA           199003
USA           200004
USA           200005
USA           200009
USA           200010
UK            199307
UK            199308
UK            199408

因此输出应该是

 Country    Date_ID
 --------------------
 USA        199003
 USA        200004
 USA        200009
 UK         199307
 UK         199408

这是解决此问题的一种方法,它至少可以追溯到 Oracle 10.2。它使用分析函数和分层查询。

WITH 子句只是用来动态构建示例数据。您不需要它 - 删除它,并在查询中使用您实际的 table 和列名。 (在 WITH 子句中,我在 CTE 名称之后声明了列,这仅适用于 Oracle 11.2 及更高版本,但 WITH 子句不是解决方案的一部分,因此我不会担心。)

with
  sample_data (country, date_id) as (
    select 'USA', 199003 from dual union all
    select 'USA', 200004 from dual union all
    select 'USA', 200005 from dual union all
    select 'USA', 200009 from dual union all
    select 'USA', 200010 from dual union all
    select 'UK' , 199307 from dual union all
    select 'UK' , 199308 from dual union all
    select 'UK' , 199408 from dual
  )
select country, date_id
from   (
         select country, date_id,
                row_number() over (partition by country order by dt) as rn,
                count(*) over (partition by country order by dt
                  range between current row 
                            and interval '4' month following) as ct
         from   (
                  select country, date_id, 
                         to_date(to_char(date_id, 'fm999999'), 'yyyymm') as dt
                  from   sample_data
                )
       )
start with rn = 1
connect by country = prior country and rn = prior rn + prior ct
;

COUNTRY    DATE_ID
------- ----------
UK          199307
UK          199408
USA         199003
USA         200004
USA         200009

为了比较,这里有一个 match_recognize 解决方案,需要 Oracle 12.1 或更高版本:

select country, date_id
from   (
         select country, date_id, 
                to_date(to_char(date_id, 'fm999999'), 'yyyymm') dt
         from   sample_data
       )
match_recognize(
  partition by country
  order by     date_id
  all rows per match
  pattern      (a {- b* -})
  define b as  dt < add_months(a.dt, 5)
);