Reputation: 187
I am trying to generate a range of 'last day of the month' dates from a given start date (01/01/2019) to the system date (sysdate). I am able to generate the date range for this using the below query:
select last_day(add_months (trunc (to_date('01/01/2019','MM/DD/YYYY'), 'MM'), Level - 1))
Month FROM Dual
CONNECT BY Level <= MONTHS_BETWEEN(sysdate, to_date('01/01/2019','MM/DD/YYYY')) + 1
order by month
I am trying to get the last record to equal the sysdate so I can calculate running balances - how can I go about adding this to the above query?
Example output of the solution:
+------------------------+
| MONTH |
+------------------------+
| 1/31/2019 12:00:00 AM |
| 2/28/2019 12:00:00 AM |
| 3/31/2019 12:00:00 AM |
| 4/30/2019 12:00:00 AM |
| 5/31/2019 12:00:00 AM |
| 6/30/2019 12:00:00 AM |
| 7/31/2019 12:00:00 AM |
| 8/31/2019 12:00:00 AM |
| 9/30/2019 12:00:00 AM |
| 10/31/2019 12:00:00 AM |
| 11/30/2019 12:00:00 AM |
| 12/31/2019 12:00:00 AM |
| 1/31/2020 12:00:00 AM |
| 2/25/2020 12:00:00 AM |
+------------------------+
Upvotes: 0
Views: 53
Reputation: 14886
When I first saw this I immediately thought a recursive CTE would be perfect. The problem I kept getting a type mismatch on the recursion that I could not resolve. It turned out Oracle 11g has a bug in recursive CTE with recurson with dates. This finally got me to updating at long last. So thanks for the question. Anyway for future viewers a recursive CTE does work.
alter session set nls_date_format = 'yyyy-mm-dd';
with date_list (dte) as
( select last_day(date '2019-01-01') from dual
union all
select least(add_months(dte,1), trunc(sysdate))
from date_list
where dte<trunc(sysdate)
)
select dte from date_list;
Upvotes: 1
Reputation: 142743
If I understood you correctly, you'd want today's date in the last line. If so, use CASE
(lines #13 - 19).
Lines #1 - 12 represent your current query.
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
SQL> WITH your_data
2 AS ( SELECT LAST_DAY (
3 ADD_MONTHS (
4 TRUNC (TO_DATE ('01/01/2019', 'MM/DD/YYYY'), 'MM'),
5 LEVEL - 1))
6 Month
7 FROM DUAL
8 CONNECT BY LEVEL <=
9 MONTHS_BETWEEN (
10 SYSDATE,
11 TO_DATE ('01/01/2019', 'MM/DD/YYYY'))
12 + 1)
13 SELECT CASE
14 WHEN TRUNC (month, 'mm') = TRUNC (SYSDATE, 'mm')
15 THEN
16 TRUNC (SYSDATE)
17 ELSE
18 month
19 END
20 month
21 FROM your_data
22 ORDER BY month;
MONTH
-------------------
31.01.2019 00:00:00
28.02.2019 00:00:00
31.03.2019 00:00:00
30.04.2019 00:00:00
31.05.2019 00:00:00
30.06.2019 00:00:00
31.07.2019 00:00:00
31.08.2019 00:00:00
30.09.2019 00:00:00
31.10.2019 00:00:00
30.11.2019 00:00:00
31.12.2019 00:00:00
31.01.2020 00:00:00
18.02.2020 00:00:00
14 rows selected.
SQL>
Upvotes: 1