Tipo de dados apropriado para manter valores percentuais?


Respostas:


132

Presumindo duas casas decimais em suas porcentagens, o tipo de dados que você usa depende de como você planeja armazenar suas porcentagens. Se você for armazenar seu equivalente fracionário (por exemplo, 100,00% armazenado como 1,0000), armazenarei os dados em um decimal(5,4)tipo de dados com uma CHECKrestrição que garante que os valores nunca excedam 1,0000 (assumindo que é o limite) e nunca vão abaixo de 0 (assumindo que seja o chão). Se você for armazenar seu valor de face (por exemplo, 100,00% é armazenado como 100,00), então você deve usar decimal(5,2)com uma CHECKrestrição apropriada . Combinado com um bom nome de coluna, torna claro para outros desenvolvedores o que são os dados e como os dados são armazenados na coluna.


12
Não deveria ser decimal(5,2)onde 2 denota o número de dígitos após o separador decimal?
Boris Callens de

2
@BorisCallens - Não acredito que perdi isso todos esses anos. Sim, isso é um erro de digitação. decimal(5,2)é o que deve ser capturado com uma restrição de verificação.
Thomas

4
Suponho que originalmente tinha decimal(5,4)e foi alterado para decimal(5,2)após o comentário acima ... Acho que decimal(5,4)seria a melhor definição - ou seja, você deseja armazenar 0 a 1 com 2 casas decimais, não 0 a 100. O motivo de ser uma porcentagem está fora de 100; então 100% é 100/100, que é 1. Fazer dessa forma faz mais sentido para a maioria dos casos (por exemplo 100% * 100% = 100%, não 10000%; 1 * 1 = 1).
JohnLBevan

4
@JohnLBevan - Gasta na forma como estão sendo armazenados. Se os valores forem armazenados conforme exibidos (por exemplo 100.00), você precisa decimal(5,2). Se os valores forem armazenados como frações (por exemplo 1.0000), você precisará decimal(5,4). Irá atualizar o post.
Thomas

Alguém pode explicar por que você precisa de 4 casas decimais? Você não pode usar 2? Como 0,91 === 91% ou 1,00 === 100%. Estou implementando isso agora e queria saber o ganho com 4 vagas. Algo como Pct decimal (10, 2) CHECK (Pct> =. 01 AND Pct <= 1). Desde já, obrigado.
MH

31
  • Segure como um decimal.
  • Adicione restrições de verificação se quiser limitar o intervalo (por exemplo, entre 0 e 100%; em alguns casos, pode haver razões válidas para ir além de 100% ou potencialmente até mesmo nos negativos).
  • Trate o valor 1 como 100%, 0,5 como 50%, etc. Isso permitirá que qualquer operação matemática funcione conforme o esperado (ou seja, ao contrário de usar o valor 100 como 100%).
  • Altere a precisão e a escala conforme necessário (estes são os dois valores entre parênteses columnName decimal(precision, scale). A precisão diz o número total de dígitos que podem ser mantidos no número, a escala diz quantos deles estão após a casa decimal, então decimal(3,2)é um número que pode ser representado como #.##; decimal(5,3)seria ##.###.
  • decimale numericsão essencialmente a mesma coisa. No entanto, decimalé compatível com ANSI, portanto, sempre use-o a menos que seja instruído de outra forma (por exemplo, pelos padrões de codificação de sua empresa).

Cenários de Exemplo

  • Para o seu caso (0,00% a 100,00%) você gostaria decimal(5,4).
  • Para o caso mais comum (0% a 100%) que você deseja decimal(3,2).
  • Em ambos os casos acima, as restrições de verificação seriam as mesmas

Exemplo:

if object_id('Demo') is null
create table Demo
    (
        Id bigint not null identity(1,1) constraint pk_Demo primary key
        , Name nvarchar(256) not null constraint uk_Demo unique 
        , SomePercentValue decimal(3,2) constraint chk_Demo_SomePercentValue check (SomePercentValue between 0 and 1)
        , SomePrecisionPercentValue decimal(5,2) constraint chk_Demo_SomePrecisionPercentValue check (SomePrecisionPercentValue between 0 and 1)
    )

Leitura adicional:


4

Eu concordo com o Thomas e eu escolheria a solução DECIMAL (5,4) pelo menos para aplicações WPF.

Dê uma olhada na String de formato numérico do MSDN para saber por quê: http://msdn.microsoft.com/en-us/library/dwhawy9k#PFormatString

O especificador de formato de porcentagem ("P") multiplica um número por 100 e o converte em uma string que representa uma porcentagem.

Então, você seria capaz de usar isso em seu código XAML:

DataFormatString="{}{0:P}"

2

Se 2 casas decimais for o seu nível de precisão, um "smallint" trataria disso no menor espaço (2 bytes). Você armazena a porcentagem multiplicada por 100.

EDIT: O tipo decimal é provavelmente uma correspondência melhor. Então você não precisa escalar manualmente. Leva 5 bytes por valor.


A Microsoft quebrou muitos de seus links ...
pcnate

0

Use numérico (n, n) onde n tem resolução suficiente para arredondar para 1,00. Por exemplo:

declare @discount numeric(9,9)
    , @quantity int
select @discount = 0.999999999
    , @quantity = 10000

select convert(money, @discount * @quantity)

3
Esta pergunta tem uma resposta aceita com uma classificação bastante alta de mais de três anos atrás. Se você está procurando perguntas antigas para responder, consulte aqui: stackoverflow.com/unanswered
valverij
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.