Reputation: 1
I am hoping for a more elegant query that generates a list of the first day of the month and the last day of the month for all months after a date such as 01/01/2013 from a read only database that has no date table. My solution works but it bothers me.
I apologize in advance for my brute force solution but here is a snippet what i am using today.
select ((add_months(trunc(sysdate,'mm'),-1))) as FirstDOM, (last_day(add_months(trunc(sysdate,'mm'),-1))) as LASTDOM from dual union ALL
select ((add_months(trunc(sysdate,'mm'),-2))), (last_day(add_months(trunc(sysdate,'mm'),-2))) from dual union ALL
select ((add_months(trunc(sysdate,'mm'),-3))), (last_day(add_months(trunc(sysdate,'mm'),-3))) from dual union ALL
select ((add_months(trunc(sysdate,'mm'),-4))), (last_day(add_months(trunc(sysdate,'mm'),-4))) from dual union ALL
select ((add_months(trunc(sysdate,'mm'),-5))), (last_day(add_months(trunc(sysdate,'mm'),-5))) from dual union ALL
select ((add_months(trunc(sysdate,'mm'),-6))), (last_day(add_months(trunc(sysdate,'mm'),-6))) from dual union ALL
select ((add_months(trunc(sysdate,'mm'),-7))), (last_day(add_months(trunc(sysdate,'mm'),-7))) from dual union ALL
select ((add_months(trunc(sysdate,'mm'),-8))), (last_day(add_months(trunc(sysdate,'mm'),-8))) from dual union ALL
select ((add_months(trunc(sysdate,'mm'),-9))), (last_day(add_months(trunc(sysdate,'mm'),-9))) from dual union ALL
select ((add_months(trunc(sysdate,'mm'),-10))), (last_day(add_months(trunc(sysdate,'mm'),-10))) from dual union ALL
select ((add_months(trunc(sysdate,'mm'),-11))), (last_day(add_months(trunc(sysdate,'mm'),-11))) from dual union ALL
select ((add_months(trunc(sysdate,'mm'),-12))), (last_day(add_months(trunc(sysdate,'mm'),-12))) from dual union ALL
select ((add_months(trunc(sysdate,'mm'),-13))), (last_day(add_months(trunc(sysdate,'mm'),-13))) from dual union ALL
select ((add_months(trunc(sysdate,'mm'),-14))), (last_day(add_months(trunc(sysdate,'mm'),-14))) from dual) fldom
but this actually continues for 60ish months.
thank you!
Upvotes: 0
Views: 584
Reputation: 142720
A hierarchical query does that in a simple manner. Here's an example:
SQL> alter session set nls_date_format = 'dd.mm.yyyy';
Session altered.
SQL> set ver off
SQL> with test (col) as
2 (select date '2013-01-01' from dual),
3 all_months as
4 (select add_months(col, level - 1) mon
5 from test
6 connect by level <= &number_of_months
7 )
8 select trunc(mon, 'mm') first_day,
9 last_day(mon) last_day
10 from all_months
11 order by 1;
Enter value for number_of_months: 15
FIRST_DAY LAST_DAY
---------- ----------
01.01.2013 31.01.2013
01.02.2013 28.02.2013
01.03.2013 31.03.2013
01.04.2013 30.04.2013
01.05.2013 31.05.2013
01.06.2013 30.06.2013
01.07.2013 31.07.2013
01.08.2013 31.08.2013
01.09.2013 30.09.2013
01.10.2013 31.10.2013
01.11.2013 30.11.2013
01.12.2013 31.12.2013
01.01.2014 31.01.2014
01.02.2014 28.02.2014
01.03.2014 31.03.2014
15 rows selected.
SQL>
Just for an example, I chose to display 15 months. You'd use something else, either a fixed value (60 - the value you mentioned), or computed (e.g. using MONTHS_BETWEEN
).
Upvotes: 1