I have a table that stores a valid "custom date" for each person. That date may legitimately be Feb 29 of a leap year. The thing is in my SQL for my report I need to pull the "last" mm/dd for from this custom date field for that employee as of the most recent year. This date is never in the future so I can compare the year in the date and if its the current year pull it as is. However if it's any previous year (can go back as far as 1900) I need to instead pull that MM/DD and as of last year. So you can see how this will be a problem since there is no Feb-29-2018.
I'm looking for the best solution on how to handle this. I need it in my select portion and my conditional block where this date I'm trying to derive has to be >= the applydtm date. Here is a sample query to replicate the error. Simply switching the Feb-29 date to Feb-28 will show it working since it doesn't encounter that invalid leap year date. I would be okay with all Feb 29 dates 'converting' to Mar 1st if need be as long as the code is efficient as possible. DB = Oracle 11g
WITH sampledata (actualcustomdtm, textfield, applydtm) AS (
SELECT
TO_DATE('02/29/2012 00:00:00','mm/dd/yyyy hh24:mi:ss'),
'Leap Year',
sysdate
FROM dual
UNION
SELECT
TO_DATE('01/15/2019 00:00:00','mm/dd/yyyy hh24:mi:ss'),
'Non-Leap Year',
sysdate
FROM dual
)
SELECT
actualcustomdtm,
CASE WHEN TO_CHAR(actualcustomdtm, 'YYYY') = TO_CHAR(SYSDATE, 'YYYY')
THEN TO_CHAR(actualcustomdtm, 'MM/DD/YYYY')
ELSE TO_CHAR(actualcustomdtm, 'MM/DD')||'/'||TO_CHAR(ADD_MONTHS(TRUNC(SYSDATE), -12), 'YYYY')
END AS "LASTACTCSTMDATE",
textfield,
applydtm
FROM sampledata
WHERE applydtm >=
TO_DATE(CASE WHEN TO_CHAR(actualcustomdtm, 'YYYY') = TO_CHAR(SYSDATE, 'YYYY')
THEN TO_CHAR(actualcustomdtm, 'MM/DD/YYYY')
ELSE TO_CHAR(actualcustomdtm, 'MM/DD')||'/'||TO_CHAR(ADD_MONTHS(TRUNC(SYSDATE), -12), 'YYYY')
END, 'MM/DD/YYYY')
I believe this logic does what you want -- getting the most recent anniversary up to or including today's date:
select dte, add_months(dte, 12),
(case when to_char(dte, 'MMDD') > to_char(sysdate, 'MMDD')
then add_months(dte, 12 * (extract(year from sysdate) - extract(year from dte) - 1))
else add_months(dte, 12 * (extract(year from sysdate) - extract(year from dte)))
end)
from (select date '2016-02-29' as dte from dual union all
select date '2018-01-03' from dual
) x;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With