Average 函数在关系数据库中如何工作?

How does the Average function work in relational databases?

我正在尝试从具有数百万行的 table 中查找值的几何平均值。对于那些不知道的人,要找到几何平均值,您将每个值乘以彼此然后除以行数。

您可能已经看到了问题;数字乘以数字将很快超过最大允许系统最大值。我找到了一个使用自然对数的好解决方案。

http://timothychenallen.blogspot.com/2006/03/sql-calculating-geometric-mean-geomean.html

然而,这让我想知道同样的问题是否也适用于算术平均数?如果您有 N 条记录,并且 N 非常大,运行 总和也可能超过系统最大值。

那么RDMS是如何计算查询期间的平均值的呢?

大多数数据库不像支持平均值那样支持 product() 函数。

但是,您可以使用日志做任何您想做的事。产品(简化版)如下:

select exp(sum(ln(x)) as product

平均值为:

select power(exp(sum(ln(x))), 1.0 / count(*)) as geoaverage

select EXP(AVG(LN(x))) as geoaverage

LN() 函数在某些平台上可能是 LOG()...

这些是示意图。 exp()ln() 以及 power() 的函数因数据库而异。另外,如果你必须考虑零或负数,逻辑更复杂。

我不知道 RDBMS 中算术平均值的确切实现,您也没有在原始问题中指定。但是 RDBMS 不需要对一列中的一百万行求和以获得算术平均值。考虑以下总结:

sum = (x1 + x2 + x3 + ... + x1000000)

那么均值可以写成

mean = sum / N = (x1 + x2 + x3 + ... + x1000000) / N, for N = 1,000,000

但是这个表达式可以像这样分解成几个部分:

mean = [(x1 + x2 + x3) / N ] + [(x4 + x5 + x6) / N] + ...

换句话说,RDBMS 可以简单地向下扫描一列中的百万行并逐段找到平均值,而没有 运行 溢出的风险。并且由于列中的每个数字大概都在存储它的类型的范围内,因此平均值本身不会溢出。

很容易检查。例如,SQL Server 2008。

DECLARE @T TABLE(i int);

INSERT INTO @T(i) VALUES
(2147483647),
(2147483647);

SELECT AVG(i) FROM @T;

结果

(2 row(s) affected)
Msg 8115, Level 16, State 2, Line 7
Arithmetic overflow error converting expression to data type int.

没有魔法。列类型为 int,服务器使用相同类型 int 的内部变量将值加在一起,中间结果超出 int.

的范围

您可以运行 对您使用的任何其他 DBMS 进行类似检查。不同的引擎可能会有不同的行为,但我希望它们都坚持列的原始类型。例如,平均两个 int100101 可能会导致 100101(仍然是 int),但永远不会 100.5.

对于 SQL 服务器,此行为是 documented。我希望所有其他引擎都有类似的东西:

AVG () computes the average of a set of values by dividing the sum of those values by the count of nonnull values. If the sum exceeds the maximum value for the data type of the return value an error will be returned.

因此,在计算简单平均值时也必须小心,而不仅仅是乘积。


这是摘自 SQL 92 Standard:

6) Let DT be the data type of the < value expression >.

9) If SUM or AVG is specified, then:

a) DT shall not be character string, bit string, or datetime.

b) If SUM is specified and DT is exact numeric with scale S, then the data type of the result is exact numeric with implementation-defined precision and scale S.

c) If AVG is specified and DT is exact numeric, then the data type of the result is exact numeric with implementation- defined precision not less than the precision of DT and implementation-defined scale not less than the scale of DT.

d) If DT is approximate numeric, then the data type of the result is approximate numeric with implementation-defined precision not less than the precision of DT.

e) If DT is interval, then the data type of the result is inter- val with the same precision as DT.

所以DBMS在计算AVG的时候可以把int转换成更大的类型,但是必须是exact numeric类型,不能是浮点数。在任何情况下,根据值,您仍然可以得到算术溢出。

一些 DBMS——特别是 Informix DBMS——将 INT 类型转换为浮点类型以进行计算:

SQL[2148]: create table t(i int);
SQL[2149]: insert into t values(214748347);
SQL[2150]: insert into t values(214748347);
SQL[2151]: insert into t values(214748347);
SQL[2152]: select avg(i) from t;
214748347.0
SQL[2153]: types on;
SQL[2154]: select i from t;
INTEGER
214748347
214748347
214748347
SQL[2155]: select avg(i) from t;
DECIMAL(32)
214748347.0
SQL[2156]: 

与其他类型类似。在某些情况下,这仍然会以溢出结束;然后你会得到一个运行时错误。但是,您很少会超过精度 - 通常需要大量行才能使总和超过限制,即使您在 atto-Zimbabwean dollars circa 2009 中计算下个世纪的美国赤字也是如此.