avg sale of quarter with previous quarter avg sale

前端 未结 3 2035
北荒
北荒 2021-01-16 08:09

I have a table one in which there are various attribute like region product,year,qtr,month,sale. I have to calculate the avg_qtr sale of each product having same region and

3条回答
  •  暗喜
    暗喜 (楼主)
    2021-01-16 09:08

    You can use the windowing clause of an analytic function if you have a single ordered value to sort by, so first create a DENSE_RANKing of year and qtr, then use that ranking in your analytic functions:

    with t1 as ( 
      select one.*
           , dense_rank() over (order by year, qtr) qord
        from one
    )
    select product
         , year
         , qtr
         , month
         , sales
         , round(avg(sales) over (partition by qord),2) qtr_avg
         , round(avg(sales) over (order by qord
                                  range between 1 preceding
                                            and 1 preceding),2) prev_qtr_avg
      from t1
    

    The above solution assumes dense quarterly data as provided in the sample data set, if however, the data is sparse along the quarter dimension you can first densify the data as in this query:

    with qtrs as (select level qtr from dual connect by level <=4)
    , t1 as ( 
      select product
           , year
           , qtrs.qtr
           , month
           , sales
           , dense_rank() over (order by year, qtrs.qtr) qord
        from qtrs
        left outer join one partition by (year)
          on one.qtr = qtrs.qtr
    )
    select product
         , year
         , qtr
         , month
         , sales
         , round(avg(sales) over (partition by qord),2) qtr_avg
         , round(avg(sales) over (order by qord
                                  range between 1 preceding
                                            and 1 preceding),2) prev_qtr_avg
      from t1
    

    This ensures that for every year represented in the data at least one row will exist for each quarter, and consequently QORD will enumerate every quarter, and gaps in the data will result in gaps in the calculated quarterly averages.

    You can also achieve a similar effect by altering the way QORD is calculated by exploiting the numeric natures of YEAR and QTR as in this example:

    with t1 as (select one.*, year*4+qtr qord from one)
    select product
         , year
         , qtr
         , month
         , sales
         , round(avg(sales) over (partition by qord),2) qtr_avg
         , round(avg(sales) over (order by qord
                                  range between 1 preceding
                                            and 1 preceding),2) prev_qtr_avg
      from t1
    

    Here no densification was required, and yet it still correctly leaves gaps in the prev_qtr_avg, but it does leave out records for missing quarters which the densified data includes.

    Combining the last two examples, and adding in your new requirement for regions a at least one row of data per quarter will be returned or generated if required for every distinct region, product and year. Both averages are partitioned by region and product and calculated per current or previous quarter as the case may be:

    with qtrs(qtr) as (select level from dual connect by level <= 4)
    , t1 as (
    select region, product, year, q.qtr, month, sales, year*4+q.qtr qord
      from qtrs q
      left join one partition by (region, product, year)
        on q.qtr = one.qtr
    )
    select region
         , product
         , year
         , qtr
         , month
         , sales
         , round(avg(sales) over (partition by region, product, qord),2) avg_sale
         , round(avg(sales) over (partition by region, product
                                  order by qord
                                  range between 1 preceding
                                            and 1 preceding),2) prev_avg_sale
      from t1
     order by year, region, qtr, product;
    

提交回复
热议问题