¿Tipo de datos apropiado para mantener valores porcentuales?

Respuestas:

132

Suponiendo dos lugares decimales en sus porcentajes, el tipo de datos que usa depende de cómo planea almacenar sus porcentajes. Si va a almacenar su equivalente fraccional (por ejemplo, 100,00% almacenado como 1,0000), almacenaría los datos en un decimal(5,4)tipo de datos con una CHECKrestricción que garantiza que los valores nunca superen 1,0000 (suponiendo que ese es el límite) y que nunca bajen de 0 (asumiendo que es el piso). Si va a almacenar su valor nominal (por ejemplo, 100,00% se almacena como 100,00), entonces debería utilizarlo decimal(5,2)con una CHECKrestricción adecuada . Combinado con un buen nombre de columna, deja en claro a otros desarrolladores cuáles son los datos y cómo se almacenan en la columna.

Thomas
fuente
12
¿No debería ser decimal(5,2)donde 2 denota el número de dígitos después del separador decimal?
Boris Callens
2
@BorisCallens - No puedo creer que me lo haya perdido todos estos años. Sí, eso es un error tipográfico. decimal(5,2)es lo que debe capturarse con una restricción de verificación.
Thomas
4
Supongo que esto originalmente tenía decimal(5,4)y se cambió decimal(5,2)después del comentario anterior ... Creo que decimal(5,4)sería la mejor definición, es decir, desea almacenar de 0 a 1 con 2 lugares decimales, no de 0 a 100. La razón por la que es un porcentaje está fuera de 100; entonces 100% es 100/100 que es 1. Hacerlo de esta manera tiene más sentido para la mayoría de los casos (por ejemplo 100% * 100% = 100%, no 10000%; 1 * 1 = 1).
JohnLBevan
4
@JohnLBevan: se gasta en cómo se almacenan. Si los valores se van a almacenar como se muestran (por ejemplo 100.00), entonces es necesario decimal(5,2). Si los valores se almacenarán como fracciones (por ejemplo 1.0000), entonces necesita decimal(5,4). Actualizará la publicación.
Thomas
¿Alguien puede explicar por qué necesita 4 lugares decimales? ¿No puedes usar 2? Como .91 === 91% o 1.00 === 100%. Estoy implementando esto ahora y me preguntaba la ganancia con 4 lugares. Algo como Pct decimal (10, 2) VERIFICAR (Pct> =. 01 Y Pct <= 1). Gracias por adelantado.
MH
31
  • Sostenga como decimal.
  • Agregue restricciones de verificación si desea limitar el rango (p. Ej., Entre 0 y 100%; en algunos casos, puede haber razones válidas para ir más allá del 100% o incluso en los negativos).
  • Trate el valor 1 como 100%, 0,5 como 50%, etc. Esto permitirá que cualquier operación matemática funcione como se espera (es decir, en lugar de usar el valor 100 como 100%).
  • Modifique la precisión y la escala según sea necesario (estos son los dos valores entre paréntesis columnName decimal(precision, scale). La precisión indica el número total de dígitos que se pueden contener en el número, la escala indica cuántos de ellos están después del lugar decimal, por lo que decimal(3,2)es un número que se puede representar como #.##; decimal(5,3)sería ##.###.
  • decimaly numericson esencialmente lo mismo. Sin embargo decimal, cumple con ANSI, así que utilícelo siempre a menos que se indique lo contrario (por ejemplo, según los estándares de codificación de su empresa).

Escenarios de ejemplo

  • Para su caso (0,00% a 100,00%) que desee decimal(5,4).
  • Para el caso más común (0% a 100%) que desee decimal(3,2).
  • En ambos de los anteriores, las restricciones de verificación serían las mismas

Ejemplo:

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)
    )

Otras lecturas:

JohnLBevan
fuente
4

Estoy de acuerdo con Thomas y elegiría la solución DECIMAL (5,4) al menos para aplicaciones WPF.

Eche un vistazo a la cadena de formato numérico de MSDN para saber por qué: http://msdn.microsoft.com/en-us/library/dwhawy9k#PFormatString

El especificador de formato de porcentaje ("P") multiplica un número por 100 y lo convierte en una cadena que representa un porcentaje.

Entonces podrá usar esto en su código XAML:

DataFormatString="{}{0:P}"
pjehan
fuente
2

Si 2 lugares decimales es su nivel de precisión, entonces un "smallint" manejaría esto en el espacio más pequeño (2 bytes). Almacena el porcentaje multiplicado por 100.

EDITAR: El tipo decimal es probablemente una mejor coincidencia. Entonces no es necesario escalar manualmente. Toma 5 bytes por valor.

mdma
fuente
Microsoft ha roto muchos de sus enlaces ...
pcnate
0

Utilice numérico (n, n) donde n tiene suficiente resolución para redondear a 1,00. Por ejemplo:

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

select convert(money, @discount * @quantity)
user2202942
fuente
3
Esta pregunta tiene una respuesta aceptada bastante alta de hace más de tres años. Si está buscando preguntas antiguas para responder, consulte aquí: stackoverflow.com/unanswered
valverij