MySQLのROUND関数の丸め演算における落とし穴の分析

MySQLのROUND関数の丸め演算における落とし穴の分析

この記事では、MySQL の ROUND 関数を使用した丸め操作の落とし穴を例を使って説明します。ご参考までに、詳細は以下の通りです。

MySQL では、クエリ結果を丸めるためにROUND関数が使用されます。しかし、最近、 ROUND関数を使用して結果を丸めると、期待どおりに動作しないことがわかりました。この記事では、他のユーザーが私と同じ間違いをしないように、この問題を記録します。

問題の説明

データテーブルテストがあるとします。テーブル作成ステートメントは次のようになります。

CREATE TABLEテスト(
 id int(11) NOT NULL AUTO_INCREMENT、
 フィールド1 bigint(10) デフォルト NULL,
 フィールド2 10進数(10,0) デフォルト NULL、
 フィールド3 int(10) デフォルト NULL,
 フィールド4 float(15,4) デフォルト NULL,
 フィールド5 float(15,4) デフォルト NULL,
 フィールド6 float(15,4) デフォルト NULL,
 主キー (id)
)ENGINE=InnoDB デフォルト文字セット=utf8;

id フィールドの他に、異なるデータ型の複数のフィールドを含む test という名前のテーブルを作成しました。このテーブルにデータを挿入してみましょう。

INSERT INTO テスト (フィールド1、フィールド2、フィールド3、フィールド4、フィールド5、フィールド6) VALUE (100、100、100、1.005、3.5、2.5);

挿入後、テーブル内のデータは次のようになります

mysql> テストから * を選択します。
+----+---------+---------+---------+--------+--------+--------+
| id | フィールド1 | フィールド2 | フィールド3 | フィールド4 | フィールド5 | フィールド6 |
+----+---------+---------+---------+--------+--------+--------+
| 1 | 100 | 100 | 100 | 1.0050 | 3.5000 | 2.5000 |
+----+---------+---------+---------+--------+--------+--------+
セット内の 1 行 (0.00 秒)

今、次の SQL を実行すると、結果はどうなると思いますか?

選択
 round(フィールド1 * フィールド4)、
 round(フィールド2 * フィールド4)、
 ラウンド(フィールド3 * フィールド4)、
 丸め(フィールド1 * 1.005)、
 丸め(フィールド2 * 1.005)、
 丸め(フィールド3 * 1.005)、
 ラウンド(フィールド5)、
 ラウンド(フィールド6)
テストから;

最初は、上記の 6 つの値はすべて 100 * 1.005 に丸められるため、結果は 101 になり、最後の 2 つは 4 と 3 になるはずだと考えていました。しかし、最終結果は予想とはまったく異なります。

************************** 1. 行 ****************************
丸め(フィールド1 * フィールド4): 100
丸め(フィールド2 * フィールド4): 100
丸め(フィールド3 * フィールド4): 100
 ラウンド(フィールド1 * 1.005): 101
 ラウンド(フィールド2 * 1.005): 101
 ラウンド(フィールド3 * 1.005): 101
    ラウンド(フィールド5): 4
    ラウンド(フィールド6): 2
セット内の 1 行 (0.00 秒)

なぜこのようなことが起こるのでしょうか?

同じ 100*1.005 ですが、データベース内のフィールドを乗算した結果が、フィールドと小数を直接乗算した結果と異なるのはなぜですか?

この問題を解決する方法がわかりません。Baidu や Google で検索しましたが、役に立ちませんでした。 。 。自分に頼るしか方法はありません。このとき最も役立つのは、公式 Web サイトのドキュメントです。そこで、ROUND 関数に関する公式 MySQL ドキュメントを検索したところ、次の 2 つのルールが含まれていました。

  • 正確な数値の場合、ROUND() は「半分を切り上げる」ルールを使用します
  • 近似値の数値の場合、結果は C ライブラリに依存します。多くのシステムでは、これは ROUND() が「最も近い偶数に丸める規則を使用することを意味します。つまり、小数部を持つ値は、最も近い偶数にROUNDます。(近似値の場合、基礎となる C 関数ライブラリに依存します。多くのシステムでは、ROUND 関数は「最も近い偶数に丸める」規則を使用します)

これら 2 つの規則から、2 つのフィールドを乗算すると、最終結果はfloat型に従って処理され、 float型はコンピューター内の正確な数値ではないため、処理結果は 2 番目の規則に従って処理されることがわかります。直接整数フィールドの結果と 1.005 などの小数演算は、演算に関係する 2 つの値が正確な数値であるため、最初の規則に従って計算されます。 field5 と field6 に対してROUND関数を実行した結果から、実際に最も近い偶数に変換されていることが明確にわかります。

要約する

この例から、MySQL でROUNDを使用する場合は特に注意する必要があることがわかります。特に、計算に関係するフィールドに浮動小数点数が含まれている場合は、計算結果が不正確になります。

MySQL 関連のコンテンツに興味のある読者は、このサイトの次のトピックをチェックしてください: 「MySQL クエリ スキル」、「MySQL トランザクション操作スキル」、「MySQL ストアド プロシージャ スキル」、「MySQL データベース ロック関連スキルの概要」、および「MySQL 共通関数の概要」

この記事が皆様のMySQLデータベース設計に役立つことを願っています。

以下もご興味があるかもしれません:
  • MySQL Where 条件文の紹介と演算子の概要
  • MySQLで使用される演算子の例
  • MySQL ノート: 演算子の使用法の詳細な説明
  • mySQL UNION演算子のデフォルトルールの研究
  • PHP MySQL アプリケーションで XOR 暗号化アルゴリズムを使用する
  • MSSQL との比較で MYSQL を学ぶ (V) - 演算子
  • MySQLでよく使われる演算子と関数の概要
  • MySQL 文字列長計算実装コード (gb2312+utf8)
  • MySQL の重要なパフォーマンス インデックスの計算と最適化方法の概要

<<:  アニメーション効果のようなVueトランジションの例

>>:  Linuxプロセス監視と自動再起動の簡単な実装方法

推薦する

Docker コンテナ アプリケーションで避けるべき 10 の悪い習慣

コンテナが企業の IT インフラストラクチャに欠かせない要素となっていることは間違いありません。コン...

MySQLに必要な共通知識のまとめ

目次主キー制約一意の主キー非 Null 制約デフォルトの制約外部キー制約1NF 2NF 3NFデータ...

CSSボックスモデルの紹介を読めば、混乱することはなくなるでしょう

Web デザインでよく耳にするプロパティ名: content、padding、border、marg...

CSS3は水平方向の中央揃え、垂直方向の中央揃え、水平方向と垂直方向の中央揃えのサンプルコードを実装しています。

フロントエンドの担当者であれば、面接でも仕事中でも、「CSS を使用して中央揃えにする」という効果に...

Vueはechartsに基づいて3次元の縦棒グラフを実装します

3次元縦棒グラフは、正面、右側、上部の3つの部分で構成されています。描画するときは、正面をグラフィッ...

SQL効率を分析する方法を説明する

Explain コマンドは、データベースのパフォーマンス問題を解決するために最初に推奨されるコマンド...

CentOS 7 での Docker プロキシの設定 (Linux での Systemd サービスの環境変数設定)

Docker デーモンは、 HTTP_PROXY 、 HTTPS_PROXY 、およびNO_PRO...

子コンポーネントを通じて親コンポーネントのプロパティを変更するための Vue のさまざまな実装方法

目次序文一般的な方法1. 親コンポーネントを介して子コンポーネントの発行イベントをリッスンしてpro...

Js における new 演算子の役割の詳細な説明

序文Js は現在最も一般的に使用されているコード操作言語であり、その中でも new 演算子は特によく...

Ubuntu 18.04 に opencv 3.2.0 をインストールするためのソリューション

opencv.zip をダウンロード依存関係を事前にインストールします。まずダウンロードソースを更新...

vue3 キャッシュページキープアライブと統合ルーティング処理の詳細な説明

目次1. はじめに2. 使用1. vue2とvue3の違い2. ページ上の一部のデータはキャッシュす...

Vue での bimface の使用に関する詳細

目次1. Vue スキャフォールディングをインストールする2. プロジェクトを作成する3.1 プロジ...

Mysqlのインポートとエクスポート時に発生する問題の解決

背景すべての業務を Docker の運用管理に移行してから、一連の落とし穴に遭遇しましたが、今回は ...

Linux での VMWare15.5 のインストールに関するチュートリアル

Linux に VMWare をインストールするには、公式 Web サイト https://www....

MySQL の null と not null、null と空の値の違いの詳細な説明 ''''

MySQL を長い間使用してきた多くの人は、これら 2 つのフィールド属性の概念をまだよく理解して...