4 votes

Calcul de la prochaine date à laquelle une combinaison jour/mois se produira

J'ai un mois et un jour ; j'essaie de déterminer la prochaine date à laquelle ce mois et ce jour existeront après une date donnée.

Par exemple, si j'ai une table comme suit, où la date de référence a le format suivant 'MMDD' . Ne m'en voulez pas, c'est le format officiel de dépôt au Royaume-Uni.

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;

Je voudrais renvoyer la première date que chaque reference_date se produit après chaque filing_date . Par exemple, dans le premier exemple, il s'agirait du 31/12/2012 et dans le dernier, du 01/08/2011.

Ma meilleure tentative, jusqu'à présent, est la suivante

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

Ce qui renvoie les bons résultats :

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

Cependant, il est aussi complètement ridicule, difficile à lire et à comprendre.

Il est également possible d'utiliser interval mais je ne vois pas vraiment en quoi cela rend moins confus le fait de déterminer ce qui se passe.

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

Y a-t-il quelque chose de vraiment évident que je manque ici ? Existe-t-il une méthode simple pour faire cela en SQL ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X