By using db<>fiddle, you agree to license everything you submit by Creative Commons CC0.
CREATE TABLE table_name ( Month, site, channel, type, revenue ) AS
SELECT DATE '2017-02-01', 'abc', 1, 'A', 50 FROM DUAL UNION ALL
SELECT DATE '2017-04-01', 'abc', 2, 'B', 100 FROM DUAL UNION ALL
SELECT DATE '2018-12-01', 'xyz', 1, 'A', 150 FROM DUAL;
3 rows affected
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
SELECT ADD_MONTHS( t.year, c.month - 1 ) AS month,
t.site,
t.channel,
t.type,
SUM( COALESCE( t.revenue, 0 ) ) OVER (
PARTITION BY t.site, t.channel, t.type, t.year
ORDER BY c.month
) AS ytd_revenue
FROM (
SELECT LEVEL AS month
FROM DUAL
CONNECT BY LEVEL <= 12
) c
LEFT OUTER JOIN (
SELECT t.*,
TRUNC( month, 'YY' ) AS year
FROM table_name t
) t
PARTITION BY ( site, channel, type, year )
ON ( c.month = EXTRACT( MONTH FROM t.month ) );
MONTH | SITE | CHANNEL | TYPE | YTD_REVENUE |
---|---|---|---|---|
2017-01-01 00:00:00 | abc | 1 | A | 0 |
2017-02-01 00:00:00 | abc | 1 | A | 50 |
2017-03-01 00:00:00 | abc | 1 | A | 50 |
2017-04-01 00:00:00 | abc | 1 | A | 50 |
2017-05-01 00:00:00 | abc | 1 | A | 50 |
2017-06-01 00:00:00 | abc | 1 | A | 50 |
2017-07-01 00:00:00 | abc | 1 | A | 50 |
2017-08-01 00:00:00 | abc | 1 | A | 50 |
2017-09-01 00:00:00 | abc | 1 | A | 50 |
2017-10-01 00:00:00 | abc | 1 | A | 50 |
2017-11-01 00:00:00 | abc | 1 | A | 50 |
2017-12-01 00:00:00 | abc | 1 | A | 50 |
2017-01-01 00:00:00 | abc | 2 | B | 0 |
2017-02-01 00:00:00 | abc | 2 | B | 0 |
2017-03-01 00:00:00 | abc | 2 | B | 0 |
2017-04-01 00:00:00 | abc | 2 | B | 100 |
2017-05-01 00:00:00 | abc | 2 | B | 100 |
2017-06-01 00:00:00 | abc | 2 | B | 100 |
2017-07-01 00:00:00 | abc | 2 | B | 100 |
2017-08-01 00:00:00 | abc | 2 | B | 100 |
2017-09-01 00:00:00 | abc | 2 | B | 100 |
2017-10-01 00:00:00 | abc | 2 | B | 100 |
2017-11-01 00:00:00 | abc | 2 | B | 100 |
2017-12-01 00:00:00 | abc | 2 | B | 100 |
2018-01-01 00:00:00 | xyz | 1 | A | 0 |
2018-02-01 00:00:00 | xyz | 1 | A | 0 |
2018-03-01 00:00:00 | xyz | 1 | A | 0 |
2018-04-01 00:00:00 | xyz | 1 | A | 0 |
2018-05-01 00:00:00 | xyz | 1 | A | 0 |
2018-06-01 00:00:00 | xyz | 1 | A | 0 |
2018-07-01 00:00:00 | xyz | 1 | A | 0 |
2018-08-01 00:00:00 | xyz | 1 | A | 0 |
2018-09-01 00:00:00 | xyz | 1 | A | 0 |
2018-10-01 00:00:00 | xyz | 1 | A | 0 |
2018-11-01 00:00:00 | xyz | 1 | A | 0 |
2018-12-01 00:00:00 | xyz | 1 | A | 150 |
WITH calendar ( month ) AS (
SELECT ADD_MONTHS( start_month, LEVEL - 1 )
FROM (
SELECT MIN( TRUNC( ADD_MONTHS( month, -3 ), 'YY' ) ) AS start_month,
ADD_MONTHS( MAX( TRUNC( ADD_MONTHS( month, -3 ), 'YY' ) ), 11 ) AS end_month
FROM table_name
)
CONNECT BY
ADD_MONTHS( start_month, LEVEL - 1 ) <= end_month
)
SELECT TO_CHAR( ADD_MONTHS( c.month, 3 ), 'YYYY-MM' ) AS month,
t.site,
t.channel,
t.type,
SUM( COALESCE( t.revenue, 0 ) ) OVER (
PARTITION BY t.site, t.channel, t.type, TRUNC( c.month, 'YY' )
ORDER BY c.month
) AS ytd_revenue
FROM calendar c
LEFT OUTER JOIN (
SELECT ADD_MONTHS( month, -3 ) AS month,
site,
channel,
type,
revenue,
TRUNC( ADD_MONTHS( month, -3 ), 'YY' ) AS year
FROM table_name t
) t
PARTITION BY ( site, channel, type )
ON ( c.month = t.month )
ORDER BY
site, channel, type, month;
MONTH | SITE | CHANNEL | TYPE | YTD_REVENUE |
---|---|---|---|---|
2016-04 | abc | 1 | A | 0 |
2016-05 | abc | 1 | A | 0 |
2016-06 | abc | 1 | A | 0 |
2016-07 | abc | 1 | A | 0 |
2016-08 | abc | 1 | A | 0 |
2016-09 | abc | 1 | A | 0 |
2016-10 | abc | 1 | A | 0 |
2016-11 | abc | 1 | A | 0 |
2016-12 | abc | 1 | A | 0 |
2017-01 | abc | 1 | A | 0 |
2017-02 | abc | 1 | A | 50 |
2017-03 | abc | 1 | A | 50 |
2017-04 | abc | 1 | A | 0 |
2017-05 | abc | 1 | A | 0 |
2017-06 | abc | 1 | A | 0 |
2017-07 | abc | 1 | A | 0 |
2017-08 | abc | 1 | A | 0 |
2017-09 | abc | 1 | A | 0 |
2017-10 | abc | 1 | A | 0 |
2017-11 | abc | 1 | A | 0 |
2017-12 | abc | 1 | A | 0 |
2018-01 | abc | 1 | A | 0 |
2018-02 | abc | 1 | A | 0 |
2018-03 | abc | 1 | A | 0 |
2018-04 | abc | 1 | A | 0 |
2018-05 | abc | 1 | A | 0 |
2018-06 | abc | 1 | A | 0 |
2018-07 | abc | 1 | A | 0 |
2018-08 | abc | 1 | A | 0 |
2018-09 | abc | 1 | A | 0 |
2018-10 | abc | 1 | A | 0 |
2018-11 | abc | 1 | A | 0 |
2018-12 | abc | 1 | A | 0 |
2019-01 | abc | 1 | A | 0 |
2019-02 | abc | 1 | A | 0 |
2019-03 | abc | 1 | A | 0 |
2016-04 | abc | 2 | B | 0 |
2016-05 | abc | 2 | B | 0 |
2016-06 | abc | 2 | B | 0 |
2016-07 | abc | 2 | B | 0 |
2016-08 | abc | 2 | B | 0 |
2016-09 | abc | 2 | B | 0 |
2016-10 | abc | 2 | B | 0 |
2016-11 | abc | 2 | B | 0 |
2016-12 | abc | 2 | B | 0 |
2017-01 | abc | 2 | B | 0 |
2017-02 | abc | 2 | B | 0 |
2017-03 | abc | 2 | B | 0 |
2017-04 | abc | 2 | B | 100 |
2017-05 | abc | 2 | B | 100 |
2017-06 | abc | 2 | B | 100 |
2017-07 | abc | 2 | B | 100 |
2017-08 | abc | 2 | B | 100 |
2017-09 | abc | 2 | B | 100 |
2017-10 | abc | 2 | B | 100 |
2017-11 | abc | 2 | B | 100 |
2017-12 | abc | 2 | B | 100 |
2018-01 | abc | 2 | B | 100 |
2018-02 | abc | 2 | B | 100 |
2018-03 | abc | 2 | B | 100 |
2018-04 | abc | 2 | B | 0 |
2018-05 | abc | 2 | B | 0 |
2018-06 | abc | 2 | B | 0 |
2018-07 | abc | 2 | B | 0 |
2018-08 | abc | 2 | B | 0 |
2018-09 | abc | 2 | B | 0 |
2018-10 | abc | 2 | B | 0 |
2018-11 | abc | 2 | B | 0 |
2018-12 | abc | 2 | B | 0 |
2019-01 | abc | 2 | B | 0 |
2019-02 | abc | 2 | B | 0 |
2019-03 | abc | 2 | B | 0 |
2016-04 | xyz | 1 | A | 0 |
2016-05 | xyz | 1 | A | 0 |
2016-06 | xyz | 1 | A | 0 |
2016-07 | xyz | 1 | A | 0 |
2016-08 | xyz | 1 | A | 0 |
2016-09 | xyz | 1 | A | 0 |
2016-10 | xyz | 1 | A | 0 |
2016-11 | xyz | 1 | A | 0 |
2016-12 | xyz | 1 | A | 0 |
2017-01 | xyz | 1 | A | 0 |
2017-02 | xyz | 1 | A | 0 |
2017-03 | xyz | 1 | A | 0 |
2017-04 | xyz | 1 | A | 0 |
2017-05 | xyz | 1 | A | 0 |
2017-06 | xyz | 1 | A | 0 |
2017-07 | xyz | 1 | A | 0 |
2017-08 | xyz | 1 | A | 0 |
2017-09 | xyz | 1 | A | 0 |
2017-10 | xyz | 1 | A | 0 |
2017-11 | xyz | 1 | A | 0 |
2017-12 | xyz | 1 | A | 0 |
2018-01 | xyz | 1 | A | 0 |
2018-02 | xyz | 1 | A | 0 |
2018-03 | xyz | 1 | A | 0 |
2018-04 | xyz | 1 | A | 0 |
2018-05 | xyz | 1 | A | 0 |
2018-06 | xyz | 1 | A | 0 |
2018-07 | xyz | 1 | A | 0 |
2018-08 | xyz | 1 | A | 0 |
2018-09 | xyz | 1 | A | 0 |
2018-10 | xyz | 1 | A | 0 |
2018-11 | xyz | 1 | A | 0 |
2018-12 | xyz | 1 | A | 150 |
2019-01 | xyz | 1 | A | 150 |
2019-02 | xyz | 1 | A | 150 |
2019-03 | xyz | 1 | A | 150 |