mysql:avg vs sum / count

时间:2014-12-15 21:36:06

标签: mysql count sum average

我有4个变量:

  • amdt_adopt
  • com_amdt_adopt
  • amdt_tabled
  • com_amdt_tabled

我想计算比率的平均值:

(amdt_adopt - com_amdt_adopt) / (amdt_tabled - com_amdt_tabled)

如果我使用内置avg功能:

select avg((amdt_adopt - com_amdt_adopt) / (amdt_tabled - com_amdt_tabled)) as final_res
from europolix.act_act
where validated=2 and com_amdt_adopt>0 and amdt_adopt>0 and com_amdt_tabled>0 and amdt_tabled>0;

我得到0.44771942

如果我使用sum,然后除以count

select 
(
    select sum((amdt_adopt - com_amdt_adopt) / (amdt_tabled - com_amdt_tabled))
    from europolix.act_act
    where validated=2 and com_amdt_adopt>0 and amdt_adopt>0 and com_amdt_tabled>0 and amdt_tabled>0
) 
/ 
(
    select count(*) 
    from europolix.act_act
    where validated=2 and com_amdt_adopt>0 and amdt_adopt>0 and com_amdt_tabled>0 and amdt_tabled>0
) as final_res;

我得到0.20883803

我有不同的结果,但这两个查询应该是等价的!怎么了?

修改

按照建议投放到decimal

select avg((cast(amdt_adopt - com_amdt_adopt as decimal(8,3)))  / (cast(amdt_tabled - com_amdt_tabled as decimal(8,3)))) as final_res
from europolix.act_act
where validated=2 and com_amdt_adopt>0 and amdt_adopt>0 and com_amdt_tabled>0 and amdt_tabled>0;

select 
(
    select sum((cast(amdt_adopt - com_amdt_adopt as decimal(8,3))) / (cast(amdt_tabled - com_amdt_tabled as decimal(8,3))))
    from europolix.act_act
    where validated=2 and com_amdt_adopt>0 and amdt_adopt>0 and com_amdt_tabled>0 and amdt_tabled>0
) 
/ 
(
    select count(*) 
    from europolix.act_act
    where validated=2 and com_amdt_adopt>0 and amdt_adopt>0 and com_amdt_tabled>0 and amdt_tabled>0
) as final_res;

结果仍然相同:(。

2 个答案:

答案 0 :(得分:4)

如果您在avg中使用的某些列的记录中包含NULL值,则avg或sum / count的结果可能很容易不同。

E.g:

create table t (id int, x int, y int);

insert into t (id, x, y) values (1, 1, 1);
insert into t (id, x, y) values (2, 2, 3);
insert into t (id, x, y) values (3, 3, 4);
insert into t (id, x, y) values (4, NULL, NULL);


select avg(x), sum(x), count(x), count(*), sum(x)/count(*) from t;

会给你:

AVG(X)  SUM(X)  COUNT(X)    COUNT(*)    SUM(X)/COUNT(*)
2       6       3           4           1.5

同样,AVG不会考虑除以零的位置。

E.g。

select avg(x/(y-x)) from t where x>0 and y>0;
2.5

select sum(x/(y-x))/count(*) from t where x>0 and y>0;
1.66666667

一种解决方案可能是使用具有以下条件的avg:

select avg(if(y-x=0, 0, x/(y-x))) from t where x>0 and y>0;
1.66666667

可以看到一个例子here

[edit]更新以考虑除以零的可能性

答案 1 :(得分:2)

正如Jack所述,当(amdt_tabled - com_amdt_tabled)=0时,avg函数不会考虑实例,但count函数会将其考虑在内。所以结果不同。

如果您不想考虑这些实例并使用sumcount函数,请在count中添加条件:

select 
(
    select sum((amdt_adopt - com_amdt_adopt) / (amdt_tabled - com_amdt_tabled))
    from europolix.act_act
    where validated=2 and com_amdt_adopt>0 and amdt_adopt>0 and com_amdt_tabled>0 and amdt_tabled>0 
) 
/ 
(
    select count(*)
    from europolix.act_act
    where validated=2 and com_amdt_adopt>0 and amdt_adopt>0 and com_amdt_tabled>0 and amdt_tabled>0 and (amdt_tabled - com_amdt_tabled)<>0
) as final_res;

如果您想将这些实例考虑在内(为0)并使用avg函数,请按照if的建议添加lp_条件:

select avg(if(amdt_tabled - com_amdt_tabled=0, 0, (amdt_adopt - com_amdt_adopt) / (amdt_tabled - com_amdt_tabled))) as final_res
from europolix.act_act
where validated=2 and com_amdt_adopt>0 and amdt_adopt>0 and com_amdt_tabled>0 and amdt_tabled>0;

<强>解决!