如何在聚合和非聚合数据集上获得相同的 AVG() 值

How to get the same value of AVG() on both aggregated & non-aggregated dataset

我们有大量数据 table 用于 return 总平均价格,但是这个和其他查询的处理时间太长,以至于我们按国家和日期汇总了结果.

这是原文的例子table:

Country   |  code | Price | Date 
--------------------------------------
IND       |  XXZ  | 7.435 | 2021-01-01
IND       |  XSZ  | 7.445 | 2021-01-01
IND       |  XAZ  | 6.435 | 2021-01-01
USA       |  XYN  | 2.524 | 2021-01-02
USA       |  AYD  | 9.524 | 2021-01-02
USA       |  XYD  | 2.534 | 2021-01-02
AUS       |  YYB  | 1.819 | 2021-01-03
AUS       |  YSB  | 4.319 | 2021-01-03
--------------------------------------
                 AVG(Price) = 5.254375
SELECT AVG(Price) from table

结果 5.254375

为了优化针对此记录集的所有查询,我们使用此表达式聚合 table:

SELECT country,sum(price),Avg(price),date 
FROM table 
GROUP BY country,date
Country |  sum(Price)| AVG(Price) | Date 
----------------------------------------------
IND     |  21.315    | 7.105      | 2021-01-01
USA     |  14.582    | 4.86066667 | 2021-01-02
AUS     |  1.638     | 3.069      | 2021-01-03
-----------------------------------------------
                   Avg = 5.011555557

When I take the Avg(Avg(Price)) = 5.011555557, this value doesn't match with the AVG(Price) = 5.254375 on non-aggregated data.

但是现在在报告中,我们仍然希望能够显示正确的平均数字,但是我们不能使用原来的table,因为您的查询处理时间太长。

如何仅使用这个聚合记录集来计算总体平均价格?

这与 SQL 并没有太大关系,而是简单的数学运算。

您需要使用原始的 count 来重建以更正 TOTAL/COUNT 表达式。

我们可以计算出,从总数来看,它很容易出现舍入误差,但它很接近,理想情况下,如果这对您来说非常重要,那么您应该记录原始计数。

SELECT country, sum(price), Avg(price), Count(1), date 
FROM table GROUP BY by country, date
Country sum(Price) AVG(Price) Count Date
IND 21.315 7.105 3 2021-01-01
USA 14.582 4.86066667 3 2021-01-02
AUS 1.638 3.069 2 2021-01-03

或者我们可以重新构造计数:

SELECT Country, totalPrice, avePrice, totalPrice/avePrice, Date
FROM AggregatedValues

_结果与上面相同 table。

但我们不能只使用 AVG,因为它使用结果中的行数,相反我们应该自己评估平均值:

SELECT SUM(sumPrice) / SUM(sumPrice/avePrice) FROM AggregatedValues

或者您是否存储了 count:

SELECT SUM(sumPrice) / SUM(Count) FROM AggregatedValues

在 sql fiddle 中查看:http://sqlfiddle.com/#!18/818872/7

我在那个数据集中看到了你的日期列,所以我们仍然可以使用 group by 在日期上汇总聚合值:

SELECT date, SUM(sumPrice) / SUM(sumPrice/avePrice) 
FROM AggregatedValues
GROUP BY date;
date Ave
2021-01-01T00:00:00Z 5.254376

http://sqlfiddle.com/#!18/818872/9

现在最终,平均值不是您期望的 5.254375 数字,这是由于存储聚合值时精度损失,如果您存储了原始计数,我们得到尽可能关闭:

已更新 fiddle,我原来的示例丢失了精度!

但这也强调了这种类型的反向平均永远无法像使用原始集那样准确!

http://sqlfiddle.com/#!18/27e7c/1

SELECT date, SUM(sumPrice) / SUM([count]) 
FROM AggregatedValues
GROUP BY date;
date Ave
2021-01-01T00:00:00Z 5.254375

您有 2 个选择

A:使用另一个只获取平均值而不获取 return 行的查询

B:获取每个国家/地区所有价格的总和以及每个国家/地区的记录数。然后你可以通过将所有价格总和除以所有记录数来得到平均值