2


estimate_itemつまり、固定精度の小数値を保持するいくつかの列を含む MySQLテーブルがあります。これが私のテーブル構造です。

テーブル名 : 見積もり_アイテム

ここに画像の説明を入力

PHP を使用してレコードを取得するときに、MySQL の関数を使用していくつかの基本的な計算を行います。使用する SQL クエリは次のとおりです。

SELECT 
    COUNT(ei.item_id) as total_item,
    SUM(ei.quantity) as total_quantity,
    SUM(ei.number_of_carton) as total_carton,
    SUM(ei.number_of_carton * ei.cbm_per_carton) as total_cbm,
    SUM(ei.quantity * ei.cost) as total_cost,
    SUM(ei.quantity * ei.rate) as total_rate,
    e.commission_amount,
    SUM(ei.quantity * ei.rate) + e.commission_amount as total_amount
FROM
    ai_estimate e
LEFT JOIN
    ai_estimate_item ei ON ei.estimate_id = e.id
WHERE
    ei.estimate_id = ?

たとえば、上記のクエリは結果を返します。

+------------+----------------+--------------+-----------+------------+------------+-------------------+--------------+
| total_item | total_quantity | total_carton | total_cbm | total_cost | total_rate | commission_amount | total_amount |
+------------+----------------+--------------+-----------+------------+------------+-------------------+--------------+
|          2 |            120 |          807 | 1122.6440 |     2.7500 |   137.5000 |           1500.00 |    1637.5000 |
+------------+----------------+--------------+-----------+------------+------------+-------------------+--------------+

次の列には 4 つの精度値が含まれているため、total_cbm_total, total_cost, total_rate, total_amountこのように 4 つの列すべての値を切り上げたいと考えています。

a) 値が1122.6440丸められる場合1122.644

b) 値が2.7500丸められる場合2.75

c) 値が137.5000丸められる場合137.50

d) 値が1200.0000次に丸められる場合1200.00

つまり、値に最低でも 2 つの精度が含まれるようにしたいのですが、値に応じて最大 3 つまたは 4 つの精度になる可能性があります。

MySQLで直接これを行う方法はありますか? またはPHPの方法?

ありがとうございます。

4

3 に答える 3

1

データベース側では、列cost、rate、およびcmb_per_cartonの末尾の0の数が、テーブル構造によって事前定義されていることに注意してください。この場合、40は次のようになります。

cost DECIMAL 19,4
rate DECIMAL 19,4
cmb_per_carton DECIMAL 19,4

これらのフィールドを使用して操作を行うと、結果は当然同じ末尾の0になります。

PHP側は、私がハッキングしたばかりの単純な関数で、探しているものを実行します。

function getDecimalFormatted($value, $minPrecision) {
    $value = (float) $value;
    return ((round((($value - floor($value))*pow(10, 5)))%1000) > 0) ? $value : number_format($value, $minPrecision, '.', '');
}

使用例:

$value = "1234.71200";
echo getDecimalFormatted($value, 2)."\n<br>";

$value = "1234.70000";
echo getDecimalFormatted($value, 2)."\n<br>";

これは以下を出力します:

1234.712
1234.70
于 2012-07-20T18:22:34.400 に答える
1

MySQL でこれを行う場合、CASE WHEN... END を追加してクエリを過度に複雑にする必要があると思います。

だから私はPHPでそれをします。

function reprecise($value)
{
    $two_digit = number_format($value, 2);
    $three_digit = number_format($value, 3);
    return (float)$two_digit == (float)$three_digit ? $two_digit : $three_digit;
}

これにはトリックが使用されています。最初に 2 桁と 3 桁の表現を計算し、次にこれらが同じ浮動小数点数であるかどうかをチェックします。そうである場合、3 桁バージョンの最後の桁は 0 でなければならず、代わりに 2 桁バージョンが使用されます。

2、3、または 4 桁に拡張するには、サイクルでそれを行うことができます。

function reprecise($value)
{
    $digits = 4;
    for ($rep = number_format($value, $digits--); $digits >= 2; $digits--)
    {
            $new = number_format($value, $digits);
            if ($new != $rep)
                    break;
            $rep = $new;
    }
    return $rep;
}

または、文字列関数は number_format よりも高速である可能性が非常に高いため:

function reprecise($value)
{
    $digits = 9;
    $base   = strrev(number_format($value, $digits));
    for ($i = 0; $i < $digits-2; $i++)
            if ($base[$i] != '0')
                    break;
    return strrev(substr($base, $i));
}
于 2012-07-20T17:30:34.963 に答える
1

1 つの方法は、正規表現を使用し0て小数点以下の数値の末尾をすべて削除し、次に小数点以下 2 桁の数値をフォーマットして 2 つの結果を比較し、最も長い方 (文字列単位) を返すことです。これは mysql で実行できますが、php でははるかに簡単です。

//$input - number to format
//$num - minimum number of decimal places to keep
function reformat($input, $num) {
    $parse = preg_replace('/(\.[1-9]*)0+$/', "$1", $input);
    $withmin = number_format($parse, 2); 
    return strlen($withmin) < strlen($parse) ? $parse : $withmin;
}
于 2012-07-20T17:45:46.193 に答える