mysql group by query with average calculation

时间:2013-09-17 12:55:29

标签: mysql

id originator revenue date
-- ---------- ------- ----------
1  acme             1 2013-09-15
2  acme             0 2013-09-15
3  acme             4 2013-09-14
4  acme             6 2013-09-13
5  acme            -6 2013-09-13
6  hello            1 2013-09-15
7  hello            0 2013-09-14
8  hello            2 2013-09-13
9  hello            5 2013-09-14

我有上表。我想根据发起人根据过去3天的收入产生的收入添加排名列

要显示的字段如下:

originator revenue toprank
---------- ------- -------
hello            8       1
acme             5       2   

2)根据以上数据,我想根据以下标准计算产生的平均收入

如果同一日期的总收入总和为0(零),则不应计算平均值。

a)发起人极端的平均值应为收入/计数的总和(收入为非零值的日期的数量),因此(4 + 1)/ 2即2.5

b)发起人你好的平均值应该是收入/计数的总和(收入为非零值的日期的数量)所以(5 + 2 + 1)/ 3,即2.6666

originator revenue toprank avg(3 days)
---------- ------- ------- -----------
hello            8       1      2.6666
acme             5       2      2.5

2 个答案:

答案 0 :(得分:0)

要在平均时忽略行,请为AVG提供空值。 NULLIF function对此有好处。

排名在MySQL中存在问题。它不支持分析函数,这使得在Oracle,MySQL,Teradata等中更容易做到。最常见的解决方法是使用计数器变量,这需要一组有序的行,这意味着总收入必须在内部查询中计算。

SELECT originator, TotalRev, Avg3Days, @rnk := @rnk + 1 AS TopRank
FROM (
  SELECT
    originator,
    SUM(revenue) AS TotalRev,
    AVG(NULLIF(revenue, 0)) AS Avg3Days
  FROM myTable
  GROUP BY originator
  ORDER BY TotalRev DESC
) Tots, (SELECT @rnk := 0) Ranks

答案 1 :(得分:0)

如果您想获取从今天开始的最后3天的值,请尝试以下操作:

SET @rank=0;

select originator, rev, @rank:=@rank+1 AS rank, avg 
FROM 
(select originator, sum(revenue) as rev, 
AVG(NULLIF(revenue, 0)) as avg
FROM t1
WHERE date >= DATE_ADD(CURDATE(), INTERVAL -3 DAY)
group by originator
order by 2 desc) as t2;

<强> SQL Fiddle..

EDITED:

如果您想从最近的日期获取过去3天的值,请尝试以下操作:

SET @rank=0;

select originator, rev, @rank:=@rank+1 AS rank, avg 
from 
(select originator, sum(revenue) as rev, 
AVG(NULLIF(revenue, 0)) as avg
from t1
WHERE date >= DATE_ADD((select max(date) from t1), INTERVAL -3 DAY)
group by originator
order by 2 desc) as t2;

<强> SQL Fiddle..