A função ROUND arredonda valores de entrada conforme o número de casas decimais especificado. No entanto, ao arredondar um literal numérico, os resultados podem ser inesperados. Por exemplo, round(0.25375, 4) retorna 0.2537 em vez do valor esperado 0.2538.
Por que isso acontece
Antes de executar a função ROUND, o MaxCompute converte literais numéricos para o tipo de dados DOUBLE. Como DOUBLE é um tipo de ponto flutuante, ele não representa todos os valores decimais com exatidão. Durante essa conversão, 0.25375 torna-se 0.2536999999..., o que resulta no arredondamento para baixo: 0.2537.
Esse problema afeta apenas literais numéricos passados diretamente à função. Quando a função ROUND processa dados de uma coluna de tabela, ela lê o tipo de dados real da coluna; portanto, o problema de precisão não ocorre.
Solução
Converta o valor de entrada para DECIMAL antes de passá-lo à função ROUND. Diferentemente de DOUBLE, o tipo DECIMAL armazena valores exatos, logo a conversão não causa perda de precisão.
O resultado exato depende da ativação do modo compatível com Hive.
Com set odps.sql.hive.compatible=false;
Tanto decimal (sem precisão especificada) quanto decimal(20,5) retornam o resultado correto:
select round(cast(0.25375 as decimal), 4);
-- Returns: 0.2538
select round(cast(0.25375 as decimal(20,5)), 4);
-- Returns: 0.2538
Com set odps.sql.hive.compatible=true;
Use decimal(p,s) com precisão e escala explícitas. O uso de decimal sem especificação de precisão retorna 0 no modo compatível com Hive:
select round(cast(0.25375 as decimal), 4);
-- Returns: 0
select round(cast(0.25375 as decimal(20,5)), 4);
-- Returns: 0.2538
No modo compatível com Hive, sempre use decimal(p,s) com precisão e escala explícitas para obter o resultado esperado.