Divisão de decimal com inteiro, como ficam as casas decimais?

Surgiu a seguinte dúvida no trabalho esse dias que foi mais ou menos assim:

Tenho duas colunas e estou realizando uma divisão entre elas. Qual vai ser o tipo retornado? O SQL Server segue a ordem de precedência do tipo do dado?

De bate pronto, a resposta é um “Sim, ele sempre vai seguir a ordem de precedência e vai retornar o tipo de dado que você está usando que possui maior precedência.”
Porém (sempre tem um porém), isso não é valido para os tipos decimais.
Para entender isso, precisamos entender três conceitos nos tipo de dados: Tamanho (length), precisão (precision) e escala (scale).
Quando você executar um ‘sp_help TB_Decimal’ (a.k.a. “ALT+F1 na tabela”), você vai ver três colunas:
– Length: quando falamos de tipos numéricos, ele retrata o tamanho em bytes que a coluna vai ocupar. Quando é um tipo texto ((n)char, (n)varchar) é a quantidade de caracteres.
– Prec: Quantidade de digitos em um número (111 = precisão de 3, 111.22 = precisão de 5).
– Scale: Quantidade de dígitos nas casas decimais (111 = escala com 0 dígitos, 111.22 = escala com 2 dígitos)
Obs: A precisão que você usar, vai mudar o tamanho que você verá no length.

Veja o exemplo abaixo:

 

Note que até para a divisão entre dois números decimais, ele não seguiu as casas decimais especificadas na tabela.
Vamos ver como o cálculo é feito (e aqui, seremos bem teóricos), usando a divisão do tipo decimal por um inteiro (valor1 / valor2), alinhando que cada coluna é uma expressão (chamada aqui de ‘e’), que possui uma precisão (‘p’) e uma escala (‘s’).
Dessa forma, temos que:
Valor1 = e1, com precisão p1 e escala s1
Valor2 = e2, com precisão p2 e escala s2

As fórmulas para o calculo da precisão e da escala para a divisão são:

Precisão
p1 – s1 + s2 + max(6, s1 + p2 + 1)
15 – 2 + 0 + max(6, 2 + 10 +1)
13 + max(6, 13)
13 + 13
26

 

Escala:
max(6, s1 + p2 + 1)
max(6, 2 + 10 + 1)
max(6, 13)
13

O resultado da consulta foi 5.0000000000000, fechando com os 13 dígitos que tivemos na escala. Poderíamos ainda ter um número onde a divisão teria como resultado mais de 13 dígitos significativos para que ele não desse overflow.

Vamos ver agora a questão do decimal / decimal

Precisão:
p1 – s1 + s2 + max(6, s1 + p2 + 1)
15 – 2 + 2 + max(6, 2 + 15 +1)
15 + max(6, 118)
15 + 18
33

Escala
max(6, s1 + p2 + 1)
max(6, 2 + 15 + 1)
max(6, 18)
18

Resultado da consulta: 5.000000000000000000.

TL/DR: Quando for realizar uma operação onde o resultado será um tipo decimal, prepare-se para tratar as casas decimais. 🙂

Fontes:

Para saber mais sobre as fórmulas de cálculo para as demais operações, veja em:
https://docs.microsoft.com/en-us/sql/t-sql/data-types/precision-scale-and-length-transact-sql
Para saber a ordem de precedência de dados
https://docs.microsoft.com/en-us/sql/t-sql/data-types/data-type-precedence-transact-sql

 

Deixe uma resposta

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.