如何在聚合和非聚合数据集上获得相同的 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:获取每个国家/地区所有价格的总和以及每个国家/地区的记录数。然后你可以通过将所有价格总和除以所有记录数来得到平均值
我们有大量数据 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:获取每个国家/地区所有价格的总和以及每个国家/地区的记录数。然后你可以通过将所有价格总和除以所有记录数来得到平均值