Cuidado com os tipos de dados MONEY e SMALLMONEY
Os tipos de dados MONEY e SMALLMONEY armazenam um número com precisão de até 4 dígitos, gerando alguns problemas em cálculos. Para entender este comportamento vamos criar uma tabela contendo duas colunas MONEY e realizar um cálculo simples de percentual.
Consulta 1
Tipo de dado MONEY
DECLARE @MoneyTab TABLE (Total MONEY, Parte MONEY); INSERT INTO @MoneyTab (Total, Parte) VALUES (271.00, 199.50), (4639.00, 4316.00), (8031.00, 7862.00) SELECT Parte, Total, (Parte / total) * 100 AS Percentagem FROM @MoneyTab Go
Agora vamos criar a mesma tabela com os mesmos dados, utilizando o tipo de dado DECIMAL.
Consulta 2
Tipo de dado DECIMAL
DECLARE @DecimalTab TABLE (Total DECIMAL(19, 4), Parte DECIMAL(19, 4)); INSERT INTO @DecimalTab (Total, Parte) VALUES (271.00, 199.50), (4639.00, 4316.00), (8031.00, 7862.00) SELECT Parte,Total, (Parte / Total) * 100 AS Percentagem FROM @DecimalTab Go
O resultado no calculo da Percentagem foi gerado com precisão superior a 4 dígitos, para reduzir a precisão vamos utilizar a função de conversão CAST, reduzindo para os mesmos 2 dígitos utilizado na Consulta 1 (tipo de dado MONEY).
Consulta 3
Tipo de dado DECIMAL com CAST.
DECLARE @DecimalTab TABLE (Total DECIMAL(19, 4), Parte DECIMAL(19, 4)); INSERT INTO @DecimalTab (Total, Parte) VALUES (271.00, 199.50), (4639.00, 4316.00), (8031.00, 7862.00) SELECT Parte,Total, cast((Parte / Total) * 100 as decimal(19,2)) AS Percentagem FROM @DecimalTab Go
Comparando os resultados:
Repare que o valor gerado pelo tipo de dado MONEY não arredonda o valor, simplesmente corta na precisão dos dois números utilizados no cálculo!
Este comportamento pode gerar diferenças importantes nos valores quando agrupamos no mês, ano, etc. Devemos evitar também utilizar MONEY e SMALLMONEY em Data Warehouse, pois é comum utilizar cálculos agregados com grandes volumes de números, potencializando a diferença no resultado.
Até o próximo post.
Saudações Tricolores,
Landry