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 ?