【问题标题】:Why precision is decreasing when multiply sum to other number为什么将总和乘以其他数字时精度会降低
【发布时间】:2013-01-14 05:15:03
【问题描述】:

我在 SQL Server 中遇到了以下错误(或功能)。

当我使用SUM (*column*) 其中column 具有numeric(18, 8) 类型并将其乘以任何其他数字(整数或十进制)时,结果精度会降低到numeric(18, 6)

这是要演示的示例脚本。

CREATE TABLE #temp (Qnty numeric(18,8))

INSERT INTO #temp (Qnty) VALUES (0.00000001)
INSERT INTO #temp (Qnty) VALUES (0.00000002)
INSERT INTO #temp (Qnty) VALUES (0.00000003)

SELECT Qnty, 1*Qnty
FROM #temp

SELECT (-1)*SUM(Qnty), SUM(Qnty), -SUM(Qnty), SUM(Qnty) * CAST(2.234 as numeric(18,8))
FROM #temp

DROP TABLE #temp

第二次 SELECT 查询的结果

0.000000    0.00000006  -0.00000006 0.000000

如您所见,我将 SUM 相乘,结果为 0.000000

谁能解释一下这种奇怪的行为?

UPD。我在 2000、2005 和 2008 SQL Server 上的 SQL Management Studio 中执行了这个查询。

【问题讨论】:

  • 有点离题(这对您的问题没有帮助),但我相信NUMERIC 不应再在 SQL Server 中使用 - DECIMAL 应该取而代之。
  • 感谢您的建议。但小数点结果相同
  • 我知道 :) 这就是为什么我说(and it doesn't help your problem)
  • 从#tmp 中选择peristanttable 并检查resultdatatype 将在Numeric(38,6) 上显示字段类型,SUM(Qnty*1.0) 将导致numeric(38, 9)

标签: sql-server sql-server-2008 sql-server-2005


【解决方案1】:

numeric(18, 8)SUM 聚合得到数据类型numeric(38, 8)

可以在此处找到将某些内容与数字相乘时如何计算结果数据类型:Precision, Scale, and Length (Transact-SQL)

常量 -1 的数据类型是 numeric(1, 0)

精度为p1 + p2 + 1 = 40
比例为s1 + s2 = 8

最大精度为 38,剩下的就是 numeric(38, 6)

在此处了解更多关于它为什么是 numeric(38, 6) 的信息:Multiplication and Division with Numerics

【讨论】:

  • 谢谢。但是为什么最大比例正好是 6?为什么不是 4 个或 8 个?
  • @VictorChekalin 根据我添加的链接“我们决定在乘法和除法中保留最小比例为 6”。
  • 谢谢。发现以下文章有用 (codeproject.com/Articles/769823/…)
【解决方案2】:

如果您阅读SUM's reference page,您会看到在十进制列上它产生NUMERIC(38,6) 的类型。您需要将 SUM 的结果转换为 NUMERIC(18,8) 以使其按照您想要的方式工作。

执行SELECT CAST(SUM(Qnty) as numeric(18,8)) * 2.234 FROM #temp 会产生0.00000013404,正如您所期望的那样。

【讨论】:

    【解决方案3】:

    【讨论】:

    • 我阅读了整个帖子,但没有找到任何可以解释观察到的问题的内容。
    • 那么您还没有阅读 Mat Henaire 的解释:...,结果应该是数字 (77, 20)。但是,这超出了 SQL Server 的最大精度,因此需要截断结果。做出了一个实现决定,牺牲一些比例以在小数点左侧获得更多数字,直到最小比例 6。所以 numeric(77,20) 实际上转换为 numeric(38, 6)。除法也会发生同样的行为。该决定是基于以下假设:小数点左侧的数字通常比右侧的数字更重要。
    • 这也是 Mikael Eriksson 在上面的回答中解释的内容
    • 你为什么不一开始就发布它(带有指向源的链接)?不幸的是,它仍然不适用于 OP,因为他的号码都是 numeric(18,8) 而不是 numeric(38,10)
    • 确实适用,操作发生时仍然超过最大值。
    猜你喜欢
    • 2022-11-02
    • 1970-01-01
    • 1970-01-01
    • 2020-01-22
    • 1970-01-01
    • 1970-01-01
    • 2013-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多