使用PARTITION OUTER JOIN
:
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 ) );
其中,对于样本数据:
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;
输出:
月 | 网站 | 频道 | 类型 | YTD_REVENUE
:----------------- | :--- | ------: | :--- | ----------:
2017-01-01 00:00:00 | 美国广播公司 | 1 | 一个 | 0
2017-02-01 00:00:00 | 美国广播公司 | 1 | 一个 | 50
2017-03-01 00:00:00 | 美国广播公司 | 1 | 一个 | 50
2017-04-01 00:00:00 | 美国广播公司 | 1 | 一个 | 50
2017-05-01 00:00:00 | 美国广播公司 | 1 | 一个 | 50
2017-06-01 00:00:00 | 美国广播公司 | 1 | 一个 | 50
2017-07-01 00:00:00 | 美国广播公司 | 1 | 一个 | 50
2017-08-01 00:00:00 | 美国广播公司 | 1 | 一个 | 50
2017-09-01 00:00:00 | 美国广播公司 | 1 | 一个 | 50
2017-10-01 00:00:00 | 美国广播公司 | 1 | 一个 | 50
2017-11-01 00:00:00 | 美国广播公司 | 1 | 一个 | 50
2017-12-01 00:00:00 | 美国广播公司 | 1 | 一个 | 50
2017-01-01 00:00:00 | 美国广播公司 | 2 | 乙| 0
2017-02-01 00:00:00 | 美国广播公司 | 2 | 乙| 0
2017-03-01 00:00:00 | 美国广播公司 | 2 | 乙| 0
2017-04-01 00:00:00 | 美国广播公司 | 2 | 乙| 100
2017-05-01 00:00:00 | 美国广播公司 | 2 | 乙| 100
2017-06-01 00:00:00 | 美国广播公司 | 2 | 乙| 100
2017-07-01 00:00:00 | 美国广播公司 | 2 | 乙| 100
2017-08-01 00:00:00 | 美国广播公司 | 2 | 乙| 100
2017-09-01 00:00:00 | 美国广播公司 | 2 | 乙| 100
2017-10-01 00:00:00 | 美国广播公司 | 2 | 乙| 100
2017-11-01 00:00:00 | 美国广播公司 | 2 | 乙| 100
2017-12-01 00:00:00 | 美国广播公司 | 2 | 乙| 100
2018-01-01 00:00:00 | xyz | 1 | 一个 | 0
2018-02-01 00:00:00 | xyz | 1 | 一个 | 0
2018-03-01 00:00:00 | xyz | 1 | 一个 | 0
2018-04-01 00:00:00 | xyz | 1 | 一个 | 0
2018-05-01 00:00:00 | xyz | 1 | 一个 | 0
2018-06-01 00:00:00 | xyz | 1 | 一个 | 0
2018-07-01 00:00:00 | xyz | 1 | 一个 | 0
2018-08-01 00:00:00 | xyz | 1 | 一个 | 0
2018-09-01 00:00:00 | xyz | 1 | 一个 | 0
2018-10-01 00:00:00 | xyz | 1 | 一个 | 0
2018-11-01 00:00:00 | xyz | 1 | 一个 | 0
2018-12-01 00:00:00 | xyz | 1 | 一个 | 150
或者,如果您想要完整的日期范围而不仅仅是每年:
WITH calendar ( month ) AS (
SELECT ADD_MONTHS( start_month, LEVEL - 1 )
FROM (
SELECT MIN( ADD_MONTHS( TRUNC( ADD_MONTHS( month, -3 ), 'YY' ), 3 ) ) AS start_month,
ADD_MONTHS( MAX( TRUNC( ADD_MONTHS( month, -3 ), 'YY' ) ), 14 ) AS end_month
FROM table_name
)
CONNECT BY
ADD_MONTHS( start_month, LEVEL - 1 ) <= end_month
)
SELECT TO_CHAR( c.month, '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 t.*,
TRUNC( month, 'YY' ) AS year
FROM table_name t
) t
PARTITION BY ( site, channel, type )
ON ( c.month = t.month )
ORDER BY
site, channel, type, month;
哪个输出:
月 | 网站 | 频道 | 类型 | YTD_REVENUE
:----------------- | :--- | ------: | :--- | ----------:
2017-01-01 00:00:00 | 美国广播公司 | 1 | 一个 | 0
2017-02-01 00:00:00 | 美国广播公司 | 1 | 一个 | 50
2017-03-01 00:00:00 | 美国广播公司 | 1 | 一个 | 50
2017-04-01 00:00:00 | 美国广播公司 | 1 | 一个 | 50
2017-05-01 00:00:00 | 美国广播公司 | 1 | 一个 | 50
2017-06-01 00:00:00 | 美国广播公司 | 1 | 一个 | 50
2017-07-01 00:00:00 | 美国广播公司 | 1 | 一个 | 50
2017-08-01 00:00:00 | 美国广播公司 | 1 | 一个 | 50
2017-09-01 00:00:00 | 美国广播公司 | 1 | 一个 | 50
2017-10-01 00:00:00 | 美国广播公司 | 1 | 一个 | 50
2017-11-01 00:00:00 | 美国广播公司 | 1 | 一个 | 50
2017-12-01 00:00:00 | 美国广播公司 | 1 | 一个 | 50
2018-01-01 00:00:00 | 美国广播公司 | 1 | 一个 | 0
2018-02-01 00:00:00 | 美国广播公司 | 1 | 一个 | 0
2018-03-01 00:00:00 | 美国广播公司 | 1 | 一个 | 0
2018-04-01 00:00:00 | 美国广播公司 | 1 | 一个 | 0
2018-05-01 00:00:00 | 美国广播公司 | 1 | 一个 | 0
2018-06-01 00:00:00 | 美国广播公司 | 1 | 一个 | 0
2018-07-01 00:00:00 | 美国广播公司 | 1 | 一个 | 0
2018-08-01 00:00:00 | 美国广播公司 | 1 | 一个 | 0
2018-09-01 00:00:00 | 美国广播公司 | 1 | 一个 | 0
2018-10-01 00:00:00 | 美国广播公司 | 1 | 一个 | 0
2018-11-01 00:00:00 | 美国广播公司 | 1 | 一个 | 0
2018-12-01 00:00:00 | 美国广播公司 | 1 | 一个 | 0
2017-01-01 00:00:00 | 美国广播公司 | 2 | 乙| 0
2017-02-01 00:00:00 | 美国广播公司 | 2 | 乙| 0
2017-03-01 00:00:00 | 美国广播公司 | 2 | 乙| 0
2017-04-01 00:00:00 | 美国广播公司 | 2 | 乙| 100
2017-05-01 00:00:00 | 美国广播公司 | 2 | 乙| 100
2017-06-01 00:00:00 | 美国广播公司 | 2 | 乙| 100
2017-07-01 00:00:00 | 美国广播公司 | 2 | 乙| 100
2017-08-01 00:00:00 | 美国广播公司 | 2 | 乙| 100
2017-09-01 00:00:00 | 美国广播公司 | 2 | 乙| 100
2017-10-01 00:00:00 | 美国广播公司 | 2 | 乙| 100
2017-11-01 00:00:00 | 美国广播公司 | 2 | 乙| 100
2017-12-01 00:00:00 | 美国广播公司 | 2 | 乙| 100
2018-01-01 00:00:00 | 美国广播公司 | 2 | 乙| 0
2018-02-01 00:00:00 | 美国广播公司 | 2 | 乙| 0
2018-03-01 00:00:00 | 美国广播公司 | 2 | 乙| 0
2018-04-01 00:00:00 | 美国广播公司 | 2 | 乙| 0
2018-05-01 00:00:00 | 美国广播公司 | 2 | 乙| 0
2018-06-01 00:00:00 | 美国广播公司 | 2 | 乙| 0
2018-07-01 00:00:00 | 美国广播公司 | 2 | 乙| 0
2018-08-01 00:00:00 | 美国广播公司 | 2 | 乙| 0
2018-09-01 00:00:00 | 美国广播公司 | 2 | 乙| 0
2018-10-01 00:00:00 | 美国广播公司 | 2 | 乙| 0
2018-11-01 00:00:00 | 美国广播公司 | 2 | 乙| 0
2018-12-01 00:00:00 | 美国广播公司 | 2 | 乙| 0
2017-01-01 00:00:00 | xyz | 1 | 一个 | 0
2017-02-01 00:00:00 | xyz | 1 | 一个 | 0
2017-03-01 00:00:00 | xyz | 1 | 一个 | 0
2017-04-01 00:00:00 | xyz | 1 | 一个 | 0
2017-05-01 00:00:00 | xyz | 1 | 一个 | 0
2017-06-01 00:00:00 | xyz | 1 | 一个 | 0
2017-07-01 00:00:00 | xyz | 1 | 一个 | 0
2017-08-01 00:00:00 | xyz | 1 | 一个 | 0
2017-09-01 00:00:00 | xyz | 1 | 一个 | 0
2017-10-01 00:00:00 | xyz | 1 | 一个 | 0
2017-11-01 00:00:00 | xyz | 1 | 一个 | 0
2017-12-01 00:00:00 | xyz | 1 | 一个 | 0
2018-01-01 00:00:00 | xyz | 1 | 一个 | 0
2018-02-01 00:00:00 | xyz | 1 | 一个 | 0
2018-03-01 00:00:00 | xyz | 1 | 一个 | 0
2018-04-01 00:00:00 | xyz | 1 | 一个 | 0
2018-05-01 00:00:00 | xyz | 1 | 一个 | 0
2018-06-01 00:00:00 | xyz | 1 | 一个 | 0
2018-07-01 00:00:00 | xyz | 1 | 一个 | 0
2018-08-01 00:00:00 | xyz | 1 | 一个 | 0
2018-09-01 00:00:00 | xyz | 1 | 一个 | 0
2018-10-01 00:00:00 | xyz | 1 | 一个 | 0
2018-11-01 00:00:00 | xyz | 1 | 一个 | 0
2018-12-01 00:00:00 | xyz | 1 | 一个 | 150
db<>在这里摆弄
财政年度(4 月至 3 月):
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;
db<>在这里摆弄