如何控制计算列的数据类型?
Posted
技术标签:
【中文标题】如何控制计算列的数据类型?【英文标题】:How do I control the datatype of a computed column? 【发布时间】:2015-01-08 02:43:47 【问题描述】:使用 SQL Server 2012...
我有两列:
Price [decimal(28,12)]
OustandingShares [decimal(38,3)] -- The 38 is overkill but alas, not my call.
当我执行 ALTER TABLE 时,我得到一个作为 [decimal(38,6)] 的计算列。我需要数据类型为 [decimal(28,12)]。
ALTER TABLE [xyz].MyTable
ADD Mv AS OustandingShares * Price
如何在此计算列上有效地获得 12 位小数?我已经尝试将OutstandingShares 转换为小数点后12 位,并围绕OutstandingShares * Price 进行转换。我得到的唯一结果是 [decimal(28,12)] 处的计算域,其中有六个尾随零。
想法?
【问题讨论】:
【参考方案1】:修复
这就是你想要的:
CONVERT(DECIMAL(28,12), (
CONVERT(DECIMAL(15, 3), [OustandingShares])
* CONVERT(DECIMAL(24, 12), [Price])
)
)
用这个测试:
SELECT CONVERT(DECIMAL(28,12),
(CONVERT(DECIMAL(24,12), 5304.987781883689)
* CONVERT(DECIMAL(15,3), 3510.88)));
结果:
18625175.503659806036
原因
由于 SQL Server 关于如何跨各种操作处理精度和缩放的规则,计算被截断。这些规则在 Precision, Scale, and Length 的 MSDN 页面中有详细说明。我们对这个案例感兴趣的细节是:
操作: e1 * e2 结果精度: p1 + p2 + 1 结果量表*: s1 + s2这里的数据类型是:
十进制(28, 12) 十进制(38, 3)这应该会导致:
精度 = (28 + 38 + 1) = 67 比例 = 15但是 DECIMAL 类型的最大长度是 38。那么给出了什么?我们现在需要注意的是,“结果量表”计算附加了一个脚注,即:
* 结果精度和小数位数的绝对最大值为 38。当结果精度大于 38 时,相应的小数位数会减小,以防止结果的整数部分被截断。
所以看来,为了让 Precision 回到 38,它砍掉了 9 个小数位。
这就是我提出的修复方法有效的原因。我将“Scale”值保持不变,因为我们不想截断进入并且扩展它们没有任何作用,因为 SQL Server 将根据需要扩展 Scale。关键在于降低精度,以便不存在截断或至少最小化。
使用DECIMAL(15, 3)
和DECIMAL(24, 12)
我们应该得到:
40 超出了限制,因此减少 2 以降低到 38,这意味着将比例减少 2 使我们真正的“结果比例”为 13,这比我们需要的多 1,甚至会看到。
【讨论】:
感谢您的回答。我担心浮点数精确到小数点后 12 位。您对此有何看法? @jermny :我对此也有一点犹豫,但到目前为止,这是我能找到的扩展有效数字范围的唯一方法。我仍在尝试其他想法,但我想我会先分享这个。但我不确定需要多少关注,因为 FLOAT 通常是准确的,理论上是不精确的,但我认为这应该在规模的远端。 @jermny :我想通了,并在不久前发布了答案,现在已经更新了完整的解释。 这是一篇绝对精彩的帖子。非常感谢!【参考方案2】:使用cast()
或convert()
。比如:
ALTER TABLE [xyz].MyTable ADD Mv AS cast(OustandingShares * Price as decimal(12, 6)
或者你想要的任何类型。
编辑:
哦,我想我明白了。问题在于计算本身。在这种情况下,请在乘法之前进行转换,这样您就不必依赖 SQL Server 的(神秘)规则来符合十进制类型。
ALTER TABLE [xyz].MyTable
ADD Mv AS cast(OustandingShares as decimal(28, 12) * cast(Price as decimal(28, 12))
我相信您的情况是计算结果的最大精度超过了允许的阈值,因此比例相应减小。这在page 的底部进行了解释。
【讨论】:
我已经提到我已经尝试过了,但我得到的只是尾随零。另外,我希望它不是 12、6,而是 28、12。 @jermny 。 . .你有尾随数字,因为你有 12 的规模。 “精度”是总位数。 “刻度”是小数点右侧的数字。 (msdn.microsoft.com/en-us/library/ms190476.aspx.) 也许你没有使用正确的类型。 感谢您提供有关术语的信息。我很抱歉。 不幸的是,这仍然不起作用:当我执行 ALTER TABLE [xyz].MyTable ADD Mv as cast((OutstandingShares * Price) as decimal(28, 12)) 它仍然有结果3510.88(股)* 5304.987781883689(价格)= 18625175.503660000000(尾随零)。 我想要 12 位小数。我需要能够表示数字 123,456,789,012.123456789012。以上是关于如何控制计算列的数据类型?的主要内容,如果未能解决你的问题,请参考以下文章