ROUND 関数は、指定された小数点以下の桁数に基づいて入力値を丸めます。ただし、数値リテラルを丸める場合、予期しない結果が表示されることがあります。たとえば、round(0.25375, 4) は期待される 0.2538 ではなく、0.2537 を返します。
発生理由
ROUND を実行する前に、MaxCompute は数値リテラルを DOUBLE データの型に変換します。DOUBLE は、すべての 10 進数値を正確に表現できない浮動小数点型です。この変換中に、0.25375 は 0.2536999999... となり、0.2537 に丸められます。
説明
この問題は、関数に直接渡される数値リテラルにのみ影響します。ROUND がテーブル列データを処理する場合、列の実際のデータの型を読み取るため、精度に関する問題は発生しません。
ソリューション
入力値を ROUND に渡す前に、DECIMAL にキャストします。DOUBLE とは異なり、DECIMAL は正確な値を格納するため、変換によって精度損失は発生しません。
正確な結果は、Hive互換モードが有効になっているかどうかによって異なります。
set odps.sql.hive.compatible=false; の場合
decimal (精度指定なし) と decimal(20,5) の両方が正しい結果を返します。
select round(cast(0.25375 as decimal), 4);
-- Returns: 0.2538
select round(cast(0.25375 as decimal(20,5)), 4);
-- Returns: 0.2538set odps.sql.hive.compatible=true; の場合
明示的な精度とスケールを持つ decimal(p,s) を使用します。精度指定なしで decimal を使用すると、Hive互換モードでは 0 を返します。
select round(cast(0.25375 as decimal), 4);
-- Returns: 0
select round(cast(0.25375 as decimal(20,5)), 4);
-- Returns: 0.2538重要
Hive互換モードでは、期待される結果を得るために、常に明示的な精度とスケールを持つ decimal(p,s) を使用してください。