Reputation: 19
Having the table below:
Year Quarter Month Revenue
2005 Q1 1 13
2006 Q1 1 10
2006 Q1 2 15
2006 Q1 3 35
2006 Q2 4 11
2006 Q2 5 15
2006 Q2 6 9
2007 Q1 1 6
2007 Q1 2 14
2007 Q1 3 7
2007 Q2 4 20
2007 Q2 5 6
2007 Q2 6 6
I need a query to calculate the year-on-year comparison of quarter-to-date revenue as below:
Year Quarter Month CUrrentQTDRevenue PreviousQTDRevenue
2005 Q1 1 13
2006 Q1 1 10 13
2006 Q1 2 25 13
2006 Q1 3 60 13
2006 Q2 4 11
2006 Q2 5 26
2006 Q2 6 35
2007 Q1 1 6 10
2007 Q1 2 20 25
2007 Q1 3 27 60
2007 Q2 4 20 11
2007 Q2 5 26 26
2007 Q2 6 32 35
I've managed to get the current year quarter-to-date revenue
SELECT Year, Quarter, Month
, SUM(Revenue) OVER (PARTITION BY Year, Quarter ORDER BY Year, Quarter, Month)
AS CurrentYearQuarterToDateRevenue
FROM revenue
but how do I get to the second part? Note that I can't simply join quarters and months since, for example, 2005 has only one month for Q1, so Q1 for 2006 will have 13 for every month.
Upvotes: 0
Views: 916
Reputation: 1269703
I think I would expand the data out and use window functions:
with yyyymm as (
select t.year, m.month, m.qtr, t.revenue, t.quarter
from (select distinct year from t) y cross join
(values (1, 1), (2, 1), . . . (12, 4)) m(month, qtr) left join
t
on t.year = y.year and t.month = m.month
)
select ym.*
from (select ym.*, lag(currentQTD, 12) over (order by year, month) as prevQTD
from (select ym.*,
sum(revenue) over (partition by year, qtr order by month) as currentQTD
from yyyymm ym
) ym
) ym
where quarter is null;
You can also use apply
:
select t.*,
sum(revenue) over (partition by year, quarter order by month) as currentQTD,
tt.prevQTD
from t outer apply
(select sum(revenue) as prevQTD
from t tt
where tt.year = t.year - 1 and
tt.quarter = t.quarter and
tt.month <= t.month
) tt;
Upvotes: 0
Reputation: 6015
In the example the prior year revenue is inconsistently applied. If the YQM revenue were cumulative by Quarter in 2007 vs 2006 as well as 2006 vs 2005, then the value of 13 would carry forward into month 2 and 3 of Q1. Something like this
with yqm_ytd_cte(Year, Quarter, Month, YQM_YTD_Revenue) as (
select Year, Quarter, Month,
sum(Revenue) over (partition by Year, Quarter order by Year, Quarter, Month)
from revenue)
select yy.*, isnull(yy_lag.YQM_YTD_Revenue, 0) as Prior_Year_YQM_YTD_Revenue
from yqm_ytd_cte yy
left join yqm_ytd_cte yy_lag on yy.Year=yy_lag.Year-1
and yy.Quarter=yy_lag.Quarter
and yy.Month=yy_lag.Month;
Upvotes: 2