A operação decimal do SQL Server não é precisa
Quando executo esta operação simples no servidor SQL:
Select 800.0 /30.0
Eu obtenho o valor 26,666666, onde mesmo se for arredondado para 6 dígitos, deve ser 26,666667. Como posso fazer com que o cálculo seja preciso? Tentei pesquisar sobre isso on-line e encontrei uma solução onde converter cada operando para um decimal de alta precisão antes da operação, mas isso não será conveniente para mim porque tenho muitos cálculos longos e complexos. acho que deve haver uma solução melhor.
Respostas
Ao usar uma divisão, no SQL Server, quaisquer dígitos após a escala resultante são truncados, não arredondados. Para sua expressão, você tem a decimal(4,1)e a decimal(3,1), o que resulta em decimal(10,6):
Precision = p1 - s1 + s2 + max(6, s1 + p2 + 1)
Scale = max(6, s1 + p2 + 1)
Como resultado, 26.66666666666666~é truncado para 26.666666.
Você pode contornar isso aumentando o tamanho da precisão e da escala e, em seguida, de CONVERTvolta à precisão e escala necessárias. Por exemplo, aumente a precisão e a escala de decimal(3,1)para decimal(5,2)e converta de volta para decimal(10,6):
SELECT CONVERT(decimal(10,6),800.0 / CONVERT(decimal(5,3),30.0));
Isso retorna 26.666667.
Isso pode ser útil:
Use ROUND (Transact-SQL)
SELECT ROUND(800.0 /30.0, 5) AS RoundValue;
Resultado:
RoundValue
26.666670
Acredito que seja porque o SQL Server considera seus números como decimalvalores (que são exatos, por exemplo, 6,6666 e 6,6667 significam exatamente esses valores, não 6 e dois terços) em vez de floatvalores (que podem funcionar com números aproximados).
Se você explicitamente lançar / converter floatem a no início, seus cálculos devem funcionar sem problemas.
Eis alguns exemplos para demonstrar a diferença entre int, decimale floatcálculos
- Dividindo 20 por 3
- Dividindo 20 por 3, depois multiplicando por 3 novamente (que matematicamente deve ser 20).
SELECT (20/3) AS int_calc,
(20/3) * 3 AS int_calc_x3,
(CAST(20 AS decimal(10,3)) /3) AS dec_calc,
(CAST(20 AS decimal(10,3)) /3) * 3 AS dec_calc_x3,
(CAST(20 AS float) /3) AS float_calc,
(CAST(20 AS float) /3) * 3 AS float_calc_x3
com os seguintes resultados
int_calc int_calc_x3 dec_calc dec_calc_x3 float_calc float_calc_x3
6 18 6.666666 19.999998 6.66666666666667 20
No seu caso, você pode usar
Select CAST(800.0 AS float) /30.0
o que resulta em 26,66666666666667
Observe que se você então multiplicar de volta por 30, obterá o resultado correto, por exemplo,
Select (CAST(800.0 AS float) /30.0) * 30
resulta em 800. Soluções que lidam com decimais não terão isso.
Observe também que, uma vez que você o tenha como um float, ele deve permanecer um float até ser convertido de volta para um decimal ou um int de alguma forma (por exemplo, salvo em uma tabela como um int). Então...
SELECT A.Num / 30
FROM (Select ((CAST(800.0 AS float) /30.0) * 30) AS Num) AS A
ainda resultará em 26,6666666666666667
Esperamos que isso o ajude em seus cálculos longos e complexos.