简体   繁体   中英

SQL get year-on-year quarter-to-date revenue

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.

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;

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM