1

我知道当您使用Money时,最好(如果不是必须的话)使用Decimal数据类型,尤其是当您使用大量资金时:)。但我想将我的产品价格存储为内存要求较低的float数字,因为它们并不真正需要这样的精度。现在,当我想计算所售产品的全部收入时,它可能会变成一个非常大的数字,而且它也必须具有很高的精度。我想知道如果我SUM在 SQL 查询中按关键字求和会产生什么结果。我猜它会存储在一个Double变量中,这肯定会失去一些精度。如何强制它使用Decimal数字进行计算?也许有人知道内部情况SQL 引擎可以回答我的问题。很高兴提到我使用 Access Database Engine,但任何一般性的答案也将不胜感激。这可能是我将使用的查询示例:

SELECT SUM(Price * Qty) FROM Invoices

或者

SELECT SUM(Amount) FROM Invoices

AmountPrice存储为数据float(Single)类型和.Qtyint32

4

3 回答 3

3

如果要将计算作为双精度进行,则将其中一个值转换为该类型:

SELECT SUM(cast(Price as double) * Qty)
FROM Invoices;

SELECT SUM(cast(Amount as double))
FROM Invoices;

真正的双精度

请注意,数据库之间的命名不一致。例如,“binary_float”为 5 个字节(基于 IEEE 4 字节浮点数),“binary_double”为 9 个字节(基于 IEEE 8 字节双精度)。但是,“float”在 SQL Server 中是 8 字节,而在 MySQL 中是 4 字节。SQL Server 和 Postgres 对 4 字节版本使用“真实”。MySQL 和 Postgres 对 8 字节版本使用“double”。

编辑:

写完之后,我看到了问题中对 Access 的引用(这应该真的是一个标签)。在 Access 中,您将使用cdbl()而不是cast()

SELECT SUM(cdbl(Price) * Qty)
FROM Invoices;

SELECT SUM(cdbl(Amount))
FROM Invoices;
于 2013-08-02T01:32:40.727 回答
1

如果在浮点数和 4 字节(无符号)整数(两者都需要相同的内存存储量)之间进行选择,则有利有弊:

  • 假设价格的格式为 $$$$$.cc(1/100 不能以浮点格式精确表示 - 单格式和双格式),浮点数无法准确处理美分,因此这将引入舍入误差在与金钱相关的应用程序中通常是不可接受的。
  • int - 假设您以美分表示价格 - 将允许 -2^31 到 2^31-2^0(约 2 * 10^9)美分范围内的精确值用于有符号值和 0 到 2^32- 2^0(约 4 * 10^9)无符号。缺点是使用美分而不是美元和美分可能感觉“不自然”,但这主要是开发人员心中的一个问题:实际的“问题”——如果你想这样称呼它们——在以美元打印价值时出现和美分,它们需要稍微复杂的格式,但与如何简化应用程序的其余部分相比,这是一个非常小的代价。

稍后,在求和或执行其他计算时 - 整数分和数量值首先转换为双精度浮点数。双精度格式允许在 -(2^53-2^0) 到 2^53-2^0 范围内精确表示整数值(假设整数美分),这可能(您需要检查)满足您的需求。但请记住,在 double 中仍然会有整数美分,需要转换为美元和美分。

编辑_ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _

“6-7 位精度的十进制数字”最容易用单精度格式表示的整数范围来解释。由于 SP 格式的有效位长为 24 位(1 隐式 + 23 显式),这允许 2^0 到 2^24-2^0 或 1 到 16777215 范围内的整数。16777215 大于 6 (999999) 但小于 7 (9999999) 个十进制数字,因此是“6-7 个十进制数字”。双精度格式具有 53 位有效数 (1 + 52),其结果为 2^0 到 2^53-2^0 的整数范围。

真正的 SP 精度是“24 个连续的二进制精度数字”。

如果您可以以 50 个单位增量使用美分,您的 SP 范围将是 2^-1 到 2^23-2^-1 或 0.5 到 8388607.5

如果您可以以 25 个单位增量使用美分,那么您的 SP 范围将是 2^-2 到 2^22-2^-2 或 0.25 到 4194303.75。

于 2013-08-02T06:54:24.623 回答
0

实际上,正如@Phylogenesis在第一条评论中所说,当我想到时,我们没有出售足够的商品来溢出double价值的精度,就像商品的价格不足以溢出价值的精度一样。float正如我猜想的那样,我测试发现,如果你运行简单SELECT SUM(Amount) FROM Invoices查询,结果将是一个double值。但是按照@Gordon Linoff的建议,对于强迫症患者来说,最安全的方法是对Decimalor使用强制转换Currency(Access)。因此 Access 语法中的查询将是:

SELECT SUM(CCur(Price) * Qty)
FROM Invoices;

SELECT SUM(CCur(Amount))
FROM Invoices;

哪个CCur函数将Single(c# float)值转换为Currency(c# decimal). 很高兴知道转换Double是不必要的,因为引擎自己做。因此,更简单且安全的方法是只运行简单查询。

于 2013-08-02T21:11:11.053 回答