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

时间:2018-11-27 19:41:37

标签: sql oracle time aggregation

我已经四处搜寻,但没有找到解决方案。 (有用的读物​​SQL to find time elapsed from multiple overlapping intervals

这是我的数据:规则是

“对于每个国家,请选择时间间隔等于或大于5个月的Date_ID”

我的工作环境是ORACLE SQL。

非常感谢。

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

1 个答案:

答案 0 :(得分:1)

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

WITH子句只是用于即时构建示例数据。您不需要它-删除它,并在查询中使用实际的表名和列名。 (在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)
);