PL / SQL连续资格相结合

时间:2014-04-11 08:45:27

标签: sql oracle date plsql

我有一组数据,其中一名成员进入,注册计划一段时间,并在完成注册后,如果他希望继续他可以在第二天注册,或者他可以休息一段时间再次注册,或者他可以完全终止。

样本数据,如

Member  Start Date  End Date    Eligibility
1   1/1/1901    12/31/2009  N
1   1/1/2010    12/31/2010  Y
1   1/1/2011    12/31/2011  Y
1   1/1/2012    12/31/2012  N
1   1/1/2013    12/31/2013  Y
1   1/1/2014    12/31/2199  N
2   1/1/1901    12/31/2009  N
2   1/1/2010    12/31/2010  Y
2   1/1/2011    12/31/2011  Y
2   1/1/2012    12/31/2012  N
2   1/1/2013    12/31/2013  Y
2   1/1/2014    12/31/2199  N

我需要将所有连续资格记录合并为一个记录,并需要输出

Member  Start Date  End Date    Eligibility
1   1/1/1901    12/31/2009  N
1   1/1/2010    12/31/2011  Y
1   1/1/2012    12/31/2012  N
1   1/1/2013    12/31/2013  Y
1   1/1/2014    12/31/2199  N
2   1/1/1901    12/31/2009  N
2   1/1/2010    12/31/2011  Y
2   1/1/2012    12/31/2012  N
2   1/1/2013    12/31/2013  Y
2   1/1/2014    12/31/2199  N

日期可能会因会员和会员资格而异......

请让我知道用PL / SQL写的逻辑

2 个答案:

答案 0 :(得分:0)

我认为这应该有效:

select
    member,
    min(start_date),
    max(end_date),
    eligibility
from
(
    select
        member,
        start_date,
        end_date,
        eligibility,
        min(CONNECT _BY_ROOT (start_date)) AS root_start,
    from
        table
    connect by 
        prior member = member AND
        prior eligibility = eligibility AND
        prior end_date+1 = start_date
    group by
        member, 
        eligibility,
        start_date,
        end_date
) x
group by
    member,
    eligibility,
    root_start

答案 1 :(得分:0)

这是一个非常简单(可能很慢)的解决方案。

选择具有匹配的下一条记录的所有记录,以便获取启动系列的记录。选择具有匹配的先前记录的所有记录,以便获得结束系列的记录。加入这些结束是在开始之后。汇总以查找每个开始日期的最短结束日期。

select 
  start_dates.member, 
  start_dates.start_date, 
  min(end_dates.end_date) as end_date,
  min(start_dates.eligibility) as eligibility
from
(  
  select * 
  from mytable 
  where exists
  (
    select * 
    from mytable next_date
    where next_date.start_date = mytable.end_date = + 1 
    and next_date.eligibility = mytable.eligibility
  )
) start_dates
join
(  
  select * 
  from mytable 
  where exists
  (
    select * 
    from mytable prev_date
    where prev_date.end_date = mytable.start_date - 1
    and prev_date.eligibility = mytable.eligibility
  )
) end_dates
on start_dates.member = end_dates.member and start_dates.start_date <= end_dates.end_date
group by start_dates.member, start_dates.start_date
order by start_dates.member, start_dates.start_date;

使用LAG和LEAD应该可以实现更优雅且可能更快的解决方案,但我现在太懒了,无法解决这个问题; - )