Estoy ejecutando SQL Server 2012
SELECT
0.15 * 30 / 360,
0.15 / 360 * 30
Resultados:
0.012500,
0.012480
Este es incluso más confuso para mí:
DECLARE @N INT = 360
DECLARE @I DECIMAL(38,26) = 0.15 * 30 / 360
DECLARE @C DECIMAL(38,26) = 1000000
SELECT @C * @I * POWER(1 + @I, @N) / ( POWER(1 + @I, @N) - 1 )
SELECT @C * (@I * POWER(1 + @I, @N) / ( POWER(1 + @I, @N) - 1 ) )
La primera selección me da el resultado correcto: 12644.44022 La segunda trunca el resultado: 12644.00000
sql-server
sql-server-2012
t-sql
decimal
cpacheco
fuente
fuente
Respuestas:
Determinar la precisión y la escala resultante de las expresiones es un nido de ratas y no creo que nadie entienda las reglas exactas en cada escenario, especialmente cuando se mezclan decimal (o flotante) e int. Ver esta respuesta de gbn .
Por supuesto, puede adaptar las expresiones para obtener lo que desea haciendo conversiones explícitas mucho más detalladas. Esto probablemente es exagerado pero:
Ninguno de los resultados se redondea incorrectamente debido a las matemáticas de coma flotante rotas o a la precisión / escala extremadamente incorrecta.
fuente
Como Aaron Bertrand mencionó, las expresiones son muy difíciles de predecir.
Si te atreves a ir allí, puedes intentar obtener una idea utilizando el siguiente fragmento:
Este es el resultado:
fuente
A pesar de las excelentes respuestas ya agregadas a esta pregunta, existe un orden de precedencia explícitamente definido para la conversión de tipos de datos en SQL Server.
Cuando un operador combina dos expresiones de diferentes tipos de datos, las reglas para la precedencia del tipo de datos especifican que el tipo de datos con la precedencia más baja se convierte al tipo de datos con la precedencia más alta. Si la conversión no es una conversión implícita compatible, se devuelve un error. Cuando ambas expresiones de operando tienen el mismo tipo de datos, el resultado de la operación tiene ese tipo de datos.
SQL Server usa el siguiente orden de precedencia para los tipos de datos:
Entonces, por ejemplo, si usted
SELECT 0.5 * 1
(multiplicando un decimal por un int) obtiene un resultado que se convierte en un valor decimal, ya quedecimal
tiene mayor prioridad que elint
tipo de datos.Consulte http://msdn.microsoft.com/en-us/library/ms190309.aspx para obtener más detalles.
Habiendo dicho todo eso, probablemente
SELECT @C * (@I * POWER(1 + @I, @N) / (POWER(1 + @I, @N) - 1 ));
debería devolver un valor decimal, ya que prácticamente todas las entradas son decimales. Curiosamente, puede forzar un resultado correcto modificando esoSELECT
para:Esto devuelve:
No puedo explicar cómo eso hace alguna diferencia, aunque claramente lo hace . Mi conjetura es el
1E0
(un flotador explícita) en lasPOWER(
fuerzas de función de SQL Server para tomar una decisión diferente en los tipos de salida para laPOWER
función. Si mi suposición es correcta, eso indicaría un posible error en laPOWER
función, ya que la documentación indica que la primera entradaPOWER()
es un flotante, o un número que puede convertirse implícitamente en un flotante.fuente
¿Estás familiarizado con la
SELECT .. INTO
sintaxis ? Es un truco útil para deconstruir situaciones como esta porque crea una tabla sobre la marcha con los tipos de datos correctos para laSELECT
lista dada .Puede dividir su cálculo en sus pasos constitutivos, aplicando las reglas de precedencia de los servidores SQL a medida que avanza, para ver cómo cambia la definición. Así es como se vería su primer ejemplo:
Esta es la salida:
fuente
(1+1)
y2
son de tipo,int
pero esta pregunta tiene un ejemplo en el que terminan produciendo un resultado de tipo diferente.