所以,
问题
我对行乘法有问题。在SQL中,有一个SUM()函数可以计算一组行中某个字段的总和。我想得到乘法,即表
SUM()
+ ------ + | 数据 + ------ + | 2 | | -1 | | 3 | + ------ +
这将是2*(-1)*3 = -6作为一个结果。我正在使用 DOUBLE 数据类型来存储我的数据值。
2*(-1)*3 = -6
我的方法
从学校数学知道,log(A x B) = log(A) + log(B)-可以用来创建所需的表达式,例如:
log(A x B) = log(A) + log(B)
SELECT IF(COUNT(IF(SIGN(`col`)=0,1,NULL)),0, IF(COUNT(IF(SIGN(`col`)<0,1,NULL))%2,-1,1) * EXP(SUM(LN(ABS(`col`))))) as product FROM `test`;
-在这里您会看到此方法的弱点-由于log(X)何时未定义X<=0-我需要在计算整个表达式之前计算负号。该小提琴提供了示例数据和对此的查询。另一个缺点是,我们需要确定列值之间是否为0(因为它是一个样本,所以在实际情况下,我将为某些条件下的表行的子集选择乘积-即,我不能简单地从我的表格中删除0-s,因为结果零积对于某些行子集是有效且预期的结果)
log(X)
X<=0
细节
而现在,终于,我的问题主要部分:如何处理的情况时,我们有这样的表达:X*Y*Z在这里X < MAXF,Y<MAXF但X*Y>MAXF和X*Y*Z<MAXF-所以我们有可能的数据类型溢出(这里MAXF是限 双 MySQL数据类型)。示例在这里。上面的查询效果很好,但是我始终可以确定它会正确处理吗?即,当某些子产品引起溢出,但整个产品都正常(无溢出)时,可能还有另一种溢出问题。
X*Y*Z
X < MAXF
Y<MAXF
X*Y>MAXF
X*Y*Z<MAXF
MAXF
还是可能有另一种查找行产品的方法?另外,表中可能有数百万条记录(-1.1<X<=1.1主要是,但可能具有100或1000之类的值,即如果我们遇到上述问题,如果乘以一定数量,则足以溢出 DOUBLE )-可能正在计算通过log会很慢吗?
-1.1<X<=1.1
log
如果您经常需要这种类型的计算,建议您将符号和对数存储在单独的列中。
这些符号可以存储为1(对于正数),-1(对于负数)和0(对于零)。
1
-1
0
可以将对数指定为零0(或任何其他值),但不应在计算中使用它。
那么计算将是:
SELECT CASE WHEN EXISTS (SELECT 1 FROM test WHERE <condition> AND datasign = 0) THEN 0 ELSE (SELECT 1-2*(SUM(datasign=-1)%2) FROM test WHERE <condition>) END AS resultsign, CASE WHEN EXISTS (SELECT 1 FROM test WHERE <condition> AND datasign = 0) THEN -1 -- undefined log for result 0 ELSE (SELECT SUM(datalog) FROM test WHERE <condition> AND datasign <> 0) END AS resultlog ;
这样,您就不会出现溢出问题。您可以检查其resultlog是否超出某些限制,或者只是尝试计算resultdata = resultsign *EXP(resultlog)并查看是否引发了错误。
resultlog
resultdata = resultsign *EXP(resultlog)