try it use connect by level
get 12 months data
then group + avg
get expected data
with CTE as (
select
TO_DATE(TO_CHAR( ADD_MONTHS(sysdate ,- (level+3)),'YYYY/MM/')||'01','yyyy/mm/dd') sDate
,TO_DATE(TO_CHAR( ADD_MONTHS(sysdate ,- level),'YYYY/MM/')||'01','yyyy/mm/dd') eDate
,level from dual
connect by level <=12
)
,CTE2 as (
select *
from CTE T1
left join T T2 on cast(T2."Month" as date) between T1.sDate and T1.eDate
)
select TO_CHAR(sDate,'MM/YY') || ' - ' || TO_CHAR(eDate,'MM/YY') as "Consecutive Months"
,round(avg("Consumption")) as "Avg. of 4 Months Consumption"
from CTE2
group by sDate,eDate
order by eDate
Result
| Consecutive Months | Avg. of 4 Months Consumption |
|--------------------|------------------------------|
| 04/17 - 07/17 | 10750 |
| 05/17 - 08/17 | 11000 |
| 06/17 - 09/17 | 11500 |
| 07/17 - 10/17 | 11500 |
| 08/17 - 11/17 | 11250 |
| 09/17 - 12/17 | 11333 |
| 10/17 - 01/18 | 11000 |
| 11/17 - 02/18 | 12000 |
| 12/17 - 03/18 | (null) |
| 01/18 - 04/18 | (null) |
| 02/18 - 05/18 | (null) |
| 03/18 - 06/18 | (null) |
Test DDL:
CREATE TABLE T
("Month" timestamp, "Consumption" int)
;
INSERT ALL
INTO T ("Month", "Consumption")
VALUES ('01-Apr-2017 12:00:00 AM', 10000)
INTO T ("Month", "Consumption")
VALUES ('01-May-2017 12:00:00 AM', 10000)
INTO T ("Month", "Consumption")
VALUES ('01-Jun-2017 12:00:00 AM', 10000)
INTO T ("Month", "Consumption")
VALUES ('01-Jul-2017 12:00:00 AM', 13000)
INTO T ("Month", "Consumption")
VALUES ('01-Aug-2017 12:00:00 AM', 11000)
INTO T ("Month", "Consumption")
VALUES ('01-Sep-2017 12:00:00 AM', 12000)
INTO T ("Month", "Consumption")
VALUES ('01-Oct-2017 12:00:00 AM', 10000)
INTO T ("Month", "Consumption")
VALUES ('01-Nov-2017 12:00:00 AM', 12000)
SELECT * FROM dual
;