10

それで、

問題

行の乗算に問題があります。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- 式全体を計算する前に負の符号を数える必要があります。このためのサンプル データとクエリは、この fiddle にあります。もう 1 つの弱点は、列の値に 0 があるかどうかを確認する必要があることです (これはサンプルであるため、実際の状況では、いくつかの条件を持つテーブル行のサブセットに対して製品を選択します。つまり、単純にはできません。テーブルから 0-s を削除します。これは、結果ゼロの積が有効であり、一部の行サブセットに対して期待される結果であるためです)。

仕様

そして最後に、私の質問の主な部分: X*Y*Zand here X < MAXF, Y<MAXF, but X*Y>MAXFand X*Y*Z<MAXF- のような式がある場合の状況の処理方法: データ型のオーバーフローが発生する可能性があります (これは、二重のMySQL データ型MAXFの制限です)。サンプルはこちら。上記のクエリはうまく機能しますが、それが適切に処理されることを常に確認できますか? つまり、一部のサブ製品がオーバーフローを引き起こしているが、製品全体は問題ない (オーバーフローなし) という、オーバーフローの問題が発生する別のケースがある可能性があります。

または、行の製品を見つける別の方法があるのでしょうか? また、テーブルには数百万のレコードがある可能性があります (-1.1<X<=1.1主に、おそらく 100 や 1000 などの値があります。つまり、上記で説明した問題がある場合に特定の量を掛けると、DOUBLEをオーバーフローするのに十分な高さです) - 計算している可能性があります。経由logは遅くなりますか?

4

3 に答える 3

3

これは効きそうだな…

SELECT IF(MOD(COUNT(data < 0),2)=1
        , EXP(SUM(LOG(data)))*-1
        , EXP(SUM(LOG(data))))
          x 
  FROM my_table;
于 2013-09-11T08:21:43.350 に答える
2

このタイプの計算が頻繁に必要な場合は、符号と対数を別々の列に保存することをお勧めします。

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)を試みてエラーがスローされるかどうかを確認できます。

于 2013-09-11T08:17:31.960 に答える