Help us understand the problem. What is going on with this article?

Oracle Databaseのround()の話

この記事は PostgreSQLのround()の話 に触発されて、Oracle Databaseでも同様の調査を行った結果です。

ROUND 関数による丸め

Oracle Database の ROUND 関数は他のデータベースと同様に数値を丸めるために使われます。しかし、データ型によって整数に丸めた場合の結果が変化します。NUMBER 型とBINARY_DOUBLE 型の列に値を格納して結果を確認します。

SQL> CREATE TABLE rd_table(c1 NUMBER(3, 1), c2 BINARY_DOUBLE);
Table created.

SQL> INSERT INTO rd_table VALUES (2.1, 2.1);
1 row created.

SQL> INSERT INTO rd_table VALUES (2.2, 2.2);
1 row created.

...

SQL> INSERT INTO rd_table VALUES (2.9, 2.9);
1 row created.

SQL> INSERT INTO rd_table VALUES (3.0, 3.0);
1 row created.

SQL> COMMIT
Commit complete.

整数値に変換するために、ROUND 関数を実行します。

SQL> SELECT c1, ROUND(c1), c2, ROUND(c2) FROM rd_table ORDER BY c1;

        C1  ROUND(C1)         C2  ROUND(C2)
---------- ---------- ---------- ----------
       2.1          2   2.1E+000   2.0E+000
       2.2          2   2.2E+000   2.0E+000
       2.3          2   2.3E+000   2.0E+000
       2.4          2   2.4E+000   2.0E+000
       2.5          3   2.5E+000   2.0E+000
       2.6          3   2.6E+000   3.0E+000
       2.7          3   2.7E+000   3.0E+000
       2.8          3   2.8E+000   3.0E+000
       2.9          3   2.9E+000   3.0E+000
         3          3   3.0E+000   3.0E+000

10 rows selected.

NUMBER 型の 2.5 に対して ROUND 関数を実行すると 3 になるのに対し、BINARY_DOUBLE 型の 2.5 に対してROUND 関数を実行すると 2.0 になっています。これは「銀行丸め」とか「偶数への丸め」と呼ばれる仕様です。端数が 0.5 の場合は偶数になるように丸めます。

ROUND(v) と ROUND(v, 0) の違い

ROUND 関数の第2パラメーターには小数点以下の桁数を指定します。この値を 0 に指定すると整数に丸められますが、BINARY_DOUBLE 型の列に対して実行すると結果が変わってきます。

SQL> SELECT c2, ROUND(c2), ROUND(c2, 0) FROM rd_table ORDER BY c1;

        C2  ROUND(C2) ROUND(C2,0)
---------- ---------- -----------
  2.1E+000   2.0E+000           2
  2.2E+000   2.0E+000           2
  2.3E+000   2.0E+000           2
  2.4E+000   2.0E+000           2
  2.5E+000   2.0E+000           3
  2.6E+000   3.0E+000           3
  2.7E+000   3.0E+000           3
  2.8E+000   3.0E+000           3
  2.9E+000   3.0E+000           3
  3.0E+000   3.0E+000           3

10 rows selected.

c2 列が 2.4 の場合、ROUND(c2) は 2.0 が返りますが、ROUND(c2, 0) は 3 が返っています。
これは第2パラメーターに 0 を指定した場合、NUMBER 型として扱われるためです。
マニュアル には下記ようにわかりにくい記述があります。

nには、任意の数値データ型、または暗黙的に数値データ型に変換可能な数値以外のデータ型を指定できます。integerを指定しない場合、このファンクションは、nの数値データ型と同じデータ型で値ROUND(n, 0)を戻します。integerを指定すると、このファンクションはNUMBERを戻します。

他のRDBMSでは?

SQL Server や DB2 ではNUMERIC 型、FLOAT 型共に四捨五入がデフォルトになるようです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした