Generate a calendar for your date range and then join it to your table and the GROUP BY the month and the desc (note: DESC is a reserved word meaning descending order and should not be used as an identifier):
WITH calendar (month) AS (
SELECT ADD_MONTHS(DATE '2019-01-01', LEVEL - 1)
FROM DUAL
CONNECT BY ADD_MONTHS(DATE '2019-01-01', LEVEL - 1) <= DATE '2019-09-01'
)
SELECT month,
MIN(id) AS id,
"DESC"
FROM calendar c
INNER JOIN table_name t
ON (c.month BETWEEN t.fromdate and t.todate)
GROUP BY month, "DESC"
ORDER BY month, id
Which, for the sample data:
CREATE TABLE table_name (ID, "DESC", FromDate, ToDate) AS
SELECT 'ID_01', 'A', DATE '2017-08-01', DATE '2020-10-01' FROM DUAL UNION ALL
SELECT 'ID_02', 'B', DATE '2019-02-01', DATE '2029-09-01' FROM DUAL UNION ALL
SELECT 'ID_03', 'C', DATE '2014-02-01', DATE '2019-02-01' FROM DUAL UNION ALL
SELECT 'ID_04', 'D', DATE '2010-04-01', DATE '2019-01-01' FROM DUAL UNION ALL
SELECT 'ID_05', 'D', DATE '2019-01-01', DATE '2019-09-01' FROM DUAL;
Outputs:
| MONTH |
ID |
DESC |
| 2019-01-01 00:00:00 |
ID_01 |
A |
| 2019-01-01 00:00:00 |
ID_03 |
C |
| 2019-01-01 00:00:00 |
ID_04 |
D |
| 2019-02-01 00:00:00 |
ID_01 |
A |
| 2019-02-01 00:00:00 |
ID_02 |
B |
| 2019-02-01 00:00:00 |
ID_03 |
C |
| 2019-02-01 00:00:00 |
ID_05 |
D |
| 2019-03-01 00:00:00 |
ID_01 |
A |
| 2019-03-01 00:00:00 |
ID_02 |
B |
| 2019-03-01 00:00:00 |
ID_05 |
D |
| 2019-04-01 00:00:00 |
ID_01 |
A |
| 2019-04-01 00:00:00 |
ID_02 |
B |
| 2019-04-01 00:00:00 |
ID_05 |
D |
| 2019-05-01 00:00:00 |
ID_01 |
A |
| 2019-05-01 00:00:00 |
ID_02 |
B |
| 2019-05-01 00:00:00 |
ID_05 |
D |
| 2019-06-01 00:00:00 |
ID_01 |
A |
| 2019-06-01 00:00:00 |
ID_02 |
B |
| 2019-06-01 00:00:00 |
ID_05 |
D |
| 2019-07-01 00:00:00 |
ID_01 |
A |
| 2019-07-01 00:00:00 |
ID_02 |
B |
| 2019-07-01 00:00:00 |
ID_05 |
D |
| 2019-08-01 00:00:00 |
ID_01 |
A |
| 2019-08-01 00:00:00 |
ID_02 |
B |
| 2019-08-01 00:00:00 |
ID_05 |
D |
| 2019-09-01 00:00:00 |
ID_01 |
A |
| 2019-09-01 00:00:00 |
ID_02 |
B |
| 2019-09-01 00:00:00 |
ID_05 |
D |
fiddle