连续和非连续日期跨度中的Oracle SQL:找到的最早日期
问题描述:
我需要你的帮助来解决这个问题:连续和非连续日期跨度中的Oracle SQL:找到的最早日期
这里是我的数据
id start_date end_date
5567 2008-04-17 2008-04-30
5567 2008-05-02 2008-07-31
5567 2008-08-01 2008-08-31
5567 2008-09-01 2009-12-31
由于是2008-04之间的流逝-30和2008-05-02要求显示失效后的最早开始日期。
id start_date end_date
5567 2008-05-02 2008-08-31
这里是另一个组数据:
id start_date end_date
5567 2008-04-17 2008-04-30
5567 2008-05-01 2008-07-31
5567 2008-08-01 2008-08-31
5567 2008-09-01 2009-12-31
在这种情况下,所有的跨度是连续的,从而所述的最早开始日期应该在输出。输出应该是:
id start_date end_date
5567 2008-04-17 2008-04-30
这里是我使用的代码:当有失误
select
id, min(start_date), contig
from (
select
id, start_date, end_date,
case
when lag(end_date) over (partition by id order by end_date) =
start_date-1 or row_number() over (partition by id order by
end_date)=1
then 'c' else 'l' end contig
from t2)
group by id, contig;
它的工作时,有跨度之间没有失误,但给两个记录。
例如,当跨度连续我的查询返回:
ID MIN(START_DATE CONTIG
5567 17-APR-08 c
但是当数据是不连续它显示两条记录:
ID MIN(START_DATE CONTIG
5567 02-MAY-08 l
5567 17-APR-08 c
但在这种情况下,我只想要第一笔记录。
我知道有一个PL/SQL解决方案,但我可以在只有SQL中实现它吗? 数据库是Oracle 11gR2。
答
我认为这会做你想要什么:
select start_date
from (select t2.start_date
from t2 left join
t2 t2p
on t2.start_date = t2p.end_date + 1
where t2p.end_date is null
order by t2.start_date nulls last
) t
where rownum = 1;
您还可以lag()
做到这一点:
select coalesce(min(case when prev_end_date is not null then start_date end),
min(start_date))
from (select t2.*, lag(t2.end_date) over (order by t2.start_date) as prev_end_date
from t2
) t
where prev_end_date is null or prev_end_date <> start_date - 1;
你的 “其他” 条件是有点棘手。你必须小心,你一直没有得到最低开始日期。
第二个解决方案就像一个魅力!感谢戈登您的时间和帮助! –