在SQL Server中,存储百分比值的最佳方式是什么?

91
我想在SQL Server中存储表示百分数的值,应该选择哪种数据类型?
答案:

我想在SQL Server中存储代表百分比的值,应该选择什么数据类型?


2
你有这些“百分比”的例子吗? - RichardOD
9
我有几个数字:23.6546767%,182%,45%。 - Shimmy Weitzhandler
5个回答

83

在99.9%的情况下,您应该使用decimal(p,s)

百分比只是一种表示概念:10%仍然是0.1。

当作为实数表达时,只需选择精度和比例以获得预期值/所需小数位数的最高值即可。对于值<100%,可以使p = s,只需根据小数位数做出决定。

但是,如果您确实需要存储100%或1,则需要p = s + 1。

这样可以允许最高达到9.xxxxxx或9xx.xxxx%,因此,如果我只需要最大为1,则会添加检查约束。


3
我需要一个介于%100-%0之间的数值,且应该允许包含两位小数(例如%xx.xx),我正在使用decimal(5,4),这对我来说效果最佳。 - Shimmy Weitzhandler
我已经阅读了你的回答,但对于开发人员来说,在处理小数时,使用语言变量会存在一些精度问题。例如,0.2无法被准确地表示,有些人建议在货币计算中避免使用小数(例如,使用欧元的分来进行计算)。groovyconsole.appspot.com/script/5078068011991040 你对此有什么建议? - Nico
1
@Nico:在数据库中永远不要使用近似数字(例如FLOATDOUBLE)。你真的不需要它们,而且它们很容易引起问题。至于分和欧元之间的区别:那是无稽之谈。DECIMAL是一种精确的数据类型;因此,存储123.45就像存储12345一样准确。在数据库中,将金额存储在其货币而不是子货币中是没有意义的;这只会让人们感到困惑,并可能导致错误的计算和意外的结果。 - Thorsten Kettner

64

decimal(p, s) 和 numeric(p, s)

p(精度):

将存储的十进制数字的最大总位数(小数点左右两侧之和)


s(标度):

将存储到小数点右侧的十进制数字的位数(-> s定义了小数位数)


0 <= s <= p.

  • p ... 总位数
  • s ... 小数点右侧的数字的位数
  • p-s ... 小数点左侧的数字的位数

示例:

CREATE TABLE dbo.MyTable
( MyDecimalColumn decimal(5,2)
 ,MyNumericColumn numeric(10,5)
);

INSERT INTO dbo.MyTable VALUES (123, 12345.12);

SELECT MyDecimalColumn, MyNumericColumn FROM dbo.MyTable;

结果:

MyDecimalColumn: 123.00 (p=5, s=2)

MyNumericColumn: 12345.12000 (p=10, s=5)

链接:msdn.microsoft.com


21

我同意,DECIMAL是存储这种类型数字的最佳方式。但为了使决策更加容易,应将其存储为1的百分比,而不是100的百分比。这样,无论“整体”数字为多少,您都可以存储所需的小数位数。因此,如果您需要6个小数位,使用DECIMAL(9,8),对于23.3436435%,您存储0.23346435。将其更改为23.346435%是一个显示问题,不是存储问题,大多数演示语言/报表编写器等都可以为您更改显示。


10
我认为在使用SQL技术时应该使用decimal(p, s)函数,其中's'表示百分比容量。 因为小数点左边的每个数字都代表一个百分比,所以'p'可以是1,但最少也要比's'大1,这样才能存储高达1000%的值。 但是SQL不允许'p'小于's'。
例如: 28.2656579879%应该被存储为decimal(13, 12),并且应该被存储为00.282656579879。 128.2656579879%应该被存储为decimal(13, 12),并且应该被存储为01.282656579879。
28%应该存储在decimal(3,2)中,即0.28。 128%应该存储在decimal(3,2)中,即1.28。
注意:如果你知道你的值永远不会达到100%,那么使用decimal(s,s)即可;否则使用decimal(s+1, s)。
等等。

为什么要先提出问题,然后立即给出详细答案呢...? - Greg Beech
@Greg:指出了问题所在。Shimmy认为它是正确的。 - gbn
1
我认为他的意思是,你应该根据你的范围需求(0-99.9、0-9999等)和精度来设置p/s。 - Mayo
@Mayo:但为什么(s+1,s)小于100%? - gbn
@gbn:s+1仅适用于大于100%的情况,因为您必须存储达到单位第一位置的项目(即不小于1)。 - Shimmy Weitzhandler
显示剩余2条评论

5

该列的数据类型应为十进制数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接