一尘不染

获取行乘积(乘法)

sql

所以,

问题

我对行乘法有问题。在SQL中,有一个SUM()函数可以计算一组行中某个字段的总和。我想得到乘法,即表

+ ------ +
| 数据
+ ------ +
| 2 |
| -1 |
| 3 |
+ ------ +

这将是2*(-1)*3 = -6作为一个结果。我正在使用 DOUBLE 数据类型来存储我的数据值。

我的方法

从学校数学知道,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,因为结果零积对于某些行子集是有效且预期的结果)

细节

而现在,终于,我的问题主要部分:如何处理的情况时,我们有这样的表达:X*Y*Z在这里X < MAXFY<MAXFX*Y>MAXFX*Y*Z<MAXF-所以我们有可能的数据类型溢出(这里MAXF是限
MySQL数据类型)。示例在这里。上面的查询效果很好,但是我始终可以确定它会正确处理吗?即,当某些子产品引起溢出,但整个产品都正常(无溢出)时,可能还有另一种溢出问题。

还是可能有另一种查找行产品的方法?另外,表中可能有数百万条记录(-1.1<X<=1.1主要是,但可能具有100或1000之类的值,即如果我们遇到上述问题,如果乘以一定数量,则足以溢出
DOUBLE )-可能正在计算通过log会很慢吗?


阅读 154

收藏
2021-03-10

共1个答案

一尘不染

如果您经常需要这种类型的计算,建议您将符号和对数存储在单独的列中。

这些符号可以存储为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)并查看是否引发了错误。

2021-03-10