Los decimales y la pérdida de precisión

T-SQL Pill

¿Alguna vez os habéis vuelto loc@s con los decimales y los redondeos de las cifras? En esta nueva T-SQLPill os cuento algo que me ha pasado recientemente y me he dado cuenta de que lo que creía saber no era del todo cierto: todo tiene sus matices si profundizas y lo llevas a situaciones más exigentes.

Manejar cifras, sobre todo las económicas y en el ámbito profesional, conllevan mucha responsabilidad y hacer operaciones con ellas, muchas veces, no resulta sencillo por los problemas del redondeo o truncamiento de los decimales.

Hasta ahora, no había tenido la necesidad de trabajar con muchos decimales y por tanto mis creencias eran sencillas:

  • Si tengo un número de 2 decimales y lo multiplico por otro número de 2 decimales, obtengo uno de cuatro decimales
  • Si tengo un número entero y lo divido entre otro número entero, obtengo un número entero
  • Si tengo un número entero y lo divido entre un número de 2 decimales, obtengo otro con decimales.

Pero la película puede cambiar si se manejan muchos decimales y SQL Server os puede sorprender (o asustar según sea el caso). Veamos un ejemplo.

Ejemplo con muchos decimales

¿Cuántos decimales esperarías obtener en esta operación?

10398,8949131684846258   ÷   8,5987416971293975

Las mates nos dicen que el resultado sería 1.209,3507724089502509947546875238

¿Y SQL Server?

¡Ups! Sólo me devuelve 6 decimales.

¿Y si casteo en un intento de forzar que me devuelva más?

Sí me devuelve más, pero los rellena a 0. ¿Por qué?

Profundicemos

¡Vamos a intentar entender algo con la ayuda de estos links!

  1. Operador “/”: https://learn.microsoft.com/es-es/sql/t-sql/language-elements/divide-transact-sql?view=sql-server-ver16
  2. Prioridad de los tipos de datos: https://learn.microsoft.com/es-es/sql/t-sql/data-types/data-type-precedence-transact-sql?view=sql-server-ver16
  3. Precisión, escala y longitud: https://learn.microsoft.com/es-es/sql/t-sql/data-types/precision-scale-and-length-transact-sql?view=sql-server-ver16

Mi primera idea fue acudir al link 1 para ver qué tipo de dato devolvía la división. Desde ahí, pasé al link 2 donde explica, en función de la prioridad, qué tipo de datos te va a devolver.

Mirando el ranking se explica por qué si yo dividía un nº entero entre un nº decimal, el resultado era un decimal. O si divido un bigint entre un int, el resultado es de tipo bigint.

Pero me quedaba un fleco por resolver, y es la razón por la que truncaba los decimales a 6. Y a eso da respuesta el link 3.

Lo primero es entender la diferencia entre Precisión, Escala y Longitud

  • Precisión: el nº de dígitos de un nº.
  • Escala: los números situados a la derecha de la coma.
  • Longitud: Nº de bytes de almacenamiento.

En el caso de los datos Numeric o Decimal, la precisión máxima permitida es 38, muy importante tenerlo en cuenta para entender el resto de la explicación.

Os animo a que leáis detenidamente esta página porque te explica en cada operador cómo calcula la escala del resultado, pero para el caso que nos ocupa, la explicación la encontramos en los comentarios:

Es decir, SQL Server llega un momento que va a truncar a 6 decimales para evitar posibles problemas de desbordamientos y no vais a poder hacer nada para evitarlo, aunque ahora, al menos ya estáis avisados. 😉

También te podría gustar...

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.