2012-08-15 51 views
4

我有一个月和一天;我正在尝试计算在给定日期之后,这个月和那天将存在的下一个日期。计算下一个日期/月份组合将发生

例如,如果我有一个表如下,其中reference_date的格式为'MMDD'。请不要为此责怪我;这是在英国提交的官方格式。

create table tmp_ben_dates (filing_date date, reference_date varchar2(4)); 
insert all 
into tmp_ben_dates values (to_date('31/12/2011','dd/mm/yyyy'), '1231') 
into tmp_ben_dates values (to_date('31/12/2011','dd/mm/yyyy'), '1130') 
into tmp_ben_dates values (to_date('31/12/2011','dd/mm/yyyy'), '0101') 
into tmp_ben_dates values (to_date('31/07/2011','dd/mm/yyyy'), '0601') 
into tmp_ben_dates values (to_date('31/07/2011','dd/mm/yyyy'), '0801') 
select * from dual; 

我想返回每个reference_date每个filing_date后发生的第一次约会。例如在第一个例子中,这将是2012年12月31日,最后是01/08/2011。

我最好的尝试,到目前为止,如下

with new_date as ( 
    select reference_date 
     , filing_date 
     , add_months(trunc(filing_date,'y') 
        , to_number(substr(reference_date,1,2)) - 1) 
      + to_number(substr(reference_date,3)) - 1 as the_date 
    from tmp_ben_dates 
     ) 
select filing_date 
    , reference_date 
    , case when filing_date < the_date then next_date 
      else add_months(the_date,12) end 
    from new_date 

它返回正确的结果:

FILING_DATE   REFE NEXT_DATE 
------------------- ---- ------------------- 
31/12/2011 00:00:00 1231 31/12/2012 00:00:00 
31/12/2011 00:00:00 1130 30/11/2012 00:00:00 
31/12/2011 00:00:00 0101 01/01/2012 00:00:00 
31/07/2011 00:00:00 0601 01/06/2012 00:00:00 
31/07/2011 00:00:00 0801 01/08/2011 00:00:00 

然而,它也完全荒谬的;难以阅读和理解。

它也可以使用interval但我真的不知道它是如何让它更容易混淆,以确定发生了什么。

with new_date as ( 
    select reference_date 
     , filing_date 
     , trunc(filing_date,'y') 
      + to_yminterval('P' 
          || to_char(to_number(substr(reference_date,1,2)) - 1) 
          || 'M') 
      + to_dsinterval('P' 
          || to_char(to_number(substr(reference_date,3)) - 1) 
          || 'D') as the_date 
    from tmp_ben_dates 
     ) 
select filing_date 
     , reference_date 
     , case when filing_date < the_date then the_date 
       else add_months(the_date,12) end as next_date 
    from new_date 

有什么真正明显的,我在这里失踪?在SQL中有这样一个简单的方法吗?

回答

2

您可能会发现这更简单。它只是将日期设置为YYYYMMDD格式,并将其作为to_date()的第二个参数:

with new_date as (
    select reference_date, filing_date, 
      to_date(to_char(filing_date, 'yyyy')||reference_date), 'yyyymmdd' 
       ) - 1 as the_date 
    from tmp_ben_dates 
) 
select filing_date, reference_date, 
     (case when filing_date < the_date then next_date 
      else add_months(the_date,12) 
     end) 
from new_date 
+0

这绝对简单一些;我完全忘记了我可以这样做,因为我通常避免使用日期进行字符串操作。 – Ben 2012-08-16 09:51:30