计算每季度的平均值

时间:2019-03-09 05:34:33

标签: sql sql-server

我有以下不同的年份数据:

yearmonth value1 
---------  ------
2016/01     33
2016/02     22
2016/03     22
2016/04     22
2016/05     22
2016/06     25
2016/07     44
2016/08     44
2016/09     44
2016/10     66
2016/11     44
2016/12     34

我想计算每季度value1的平均值。     考虑如下: Quarter 1 = month 01 till month 03 Quarter 2 = month 01 till month 06 Quarter 3 = month 01 till month 09 Quarter 4 = month 01 till month 12

我尝试使用over,但未获取正确的数据。

5 个答案:

答案 0 :(得分:0)

drop table tab1;
create table tab1 (
    yearmonth char(7),
    val number
);
insert into tab1 values('2016/02', 12);
insert into tab1 values('2017/09', 10);
insert into tab1 values('2018/11', 8);
insert into tab1 values('2013/07', 6);
insert into tab1 values('2014/12', 5);
insert into tab1 values('2016/08', 25);
insert into tab1 values('2013/06', 6);
insert into tab1 values('2013/04', 6);


--version 1
select q, round(avg(val),4) as avg_val
from (
    select a.*,
    to_char(to_date(yearmonth, 'yyyy/MM'),'Q') as Q -- convert string to date and get Q
    from tab1 a
)
group by q
order by q

-- version 2
select 
avg(case when q <= 1 then val end) as q1_cum,
avg(case when q <= 2 then val end) as q2_cum,
avg(case when q <= 3 then val end) as q3_cum,
avg(case when q <= 4 then val end) as q4_cum
from (
    select a.*,
    to_number(to_char(to_date(yearmonth, 'yyyy/MM'),'Q')) as q -- convert string to date and get Q
    from tab1 a
) a

答案 1 :(得分:0)

在SQL Server 2008中:

我做了四分之一的时间,您可以尝试类似的方法:

create table calculation
(
 yearmonth varchar(200),
 value1 float
 );

  insert into calculation values('2016/01',33);
  insert into calculation values('2016/02',22);
  insert into calculation values('2016/03',22);
  insert into calculation values('2016/04',22);
  insert into calculation values('2016/05',22);
  insert into calculation values('2016/06',25);

  select
  avg(case when yearmonth between '2016/01' and '2016/03' then value1 end) as qtr1
  from calculation

注意: 以正确的格式存储日期

答案 2 :(得分:0)

我附上了SQL Server版本-上一个是Oracle版本::)

create table tab1 (
    yearmonth varchar(7),
    val int
);
insert into tab1 values('2016/02', 12);
insert into tab1 values('2017/09', 10);
insert into tab1 values('2018/11', 8);
insert into tab1 values('2013/07', 6);
insert into tab1 values('2014/12', 5);
insert into tab1 values('2016/08', 25);
insert into tab1 values('2013/06', 6);
insert into tab1 values('2013/04', 6);

select 
avg(case when b.q <= 1 then val end) as q1_cum,
avg(case when b.q <= 2 then val end) as q2_cum,
avg(case when b.q <= 3 then val end) as q3_cum,
avg(case when b.q <= 4 then val end) as q4_cum
from (
    select a.*, 
    datepart(quarter,convert(date,(yearmonth + '/01'),120)) as q
    from tab1 a
) b

答案 3 :(得分:0)

尝试在列yearmonth中添加一天,以便能够使用DATEPART函数。 然后,您就有可能在季度的VALUE之前获得平均PARTITIONs

SELECT 
  q.yearmonth
, q.QuarterPart
, AVG(q.val)  OVER (PARTITION BY q.QuarterPart ORDER BY q.QuarterPart) AvgByQuarter
FROM 
(
SELECT 
  t.yearmonth
, t.val
, DATEPART(QUARTER, concat(t.yearmonth, '/01')) QuarterPart
FROM @table t
)q

和示例数据:

DECLARE @table TABLE 
(
    yearmonth VARCHAR(10),
    val int
);
insert into @table values('2016/01', 33);
insert into @table values('2016/02', 22);
insert into @table values('2016/03', 22);
insert into @table values('2016/04', 22);
insert into @table values('2016/05', 22);
insert into @table values('2016/06', 25);
insert into @table values('2016/07', 44);
insert into @table values('2016/08', 44);
insert into @table values('2016/09', 44);
insert into @table values('2016/10', 66);
insert into @table values('2016/11', 44);
insert into @table values('2016/12', 34);

输出:

yearmonth   val QuarterPart AvgByQuarter
2016/01     33      1           25
2016/02     22      1           25
2016/03     22      1           25
2016/04     22      2           23
2016/05     22      2           23
2016/06     25      2           23
2016/07     44      3           44
2016/08     44      3           44
2016/09     44      3           44
2016/10     66      4           48
2016/11     44      4           48
2016/12     34      4           48

答案 4 :(得分:0)

有趣,您需要累积个季度。这使得这有些棘手。无论如何,我不会为此使用日期算法,因为源数据不是日期。

select q, avg(value1)
from t cross apply
     (values ('q1'),
             (case when right(yearmonth, 2) > '03' then 'q2'  end),
             (case when right(yearmonth, 2) > '06' then 'q3' end),
             (case when right(yearmonth, 2) > '09' then 'q4' end)
     ) q
where q is not null
group by q;

实际上,我还将在left(yearmonth, 4)select中都包含年份group by

如果您不想要累积结果,则:

select left(yearmonth, 4) as yyyy, q, 
       avg(value1)
from t cross apply
     (values (case when right(yearmonth, 2) <= '03' then 'q1'
                   when right(yearmonth, 2) <= '06' then 'q2'
                   when right(yearmonth, 2) <= '09' then 'q3'
                   else 'q4'
              end)
     ) q
where q is not null
group by eft(yearmonth, 4), q;

您也可以获取累计平均值:

select left(yearmonth, 4) as yyyy, q, 
       avg(value1),
       (sum(sum(value1)) over (partition by left(yearmonth, 4) order by q) /
        sum(count(*)) over (partition by left(yearmonth, 4) order by q)
       ) as cumulative_average