我知道当您使用 Money 时,使用Decimal
数据类型会更好(如果不是必须的话),尤其是当您使用大额资金时:)。但是我希望将我的产品的价格存储为较少的内存要求float
数字,因为它们并不需要这么精确。现在,当我想计算所售产品的整体收入时,它可能会成为一个非常大的数字,它也必须具有很高的精度。我想知道如果我在SQL查询中通过SUM
关键字进行求和,结果会是什么。我想它会存储在Double
变量中,这肯定会失去一些精确度。如何强制它使用Decimal
数字进行计算?也许知道SQL引擎的 internals 的人可以回答我的问题。很高兴提到我使用Access数据库引擎,但任何一般的答案也将受到赞赏。这可能是我将使用的查询示例:
SELECT SUM(Price * Qty) FROM Invoices
或
SELECT SUM(Amount) FROM Invoices
Amount
和Price
存储为float(Single)
数据类型,Qty
存储为int32
。
答案 0 :(得分:3)
如果要将计算作为double进行计算,则将其中一个值强制转换为该类型:
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使用“real”作为4字节版本。 MySQL和Postgres对8字节版本使用“double”。
编辑:
写完之后,我在问题中看到了对Access的引用(这应该是一个标签)。在Access中,您可以使用cdbl()
代替cast()
:
SELECT SUM(cdbl(Price) * Qty)
FROM Invoices;
SELECT SUM(cdbl(Amount))
FROM Invoices;
答案 1 :(得分:1)
如果选择在float和4字节(无符号)int之间(两者都需要在内存中存储相同的存储量),则有利有弊:
稍后,在求和或执行其他计算时,整数分和数值首先转换为双精度浮点。双精度格式允许精确地表示整数值(假设整数美分) - (2 ^ 53-2 ^ 0)到2 ^ 53-2 ^ 0,这可能(您需要检查)满足您的需求。但请记住,在双倍中你仍然会有整数美分,需要转换成美元和美分。
<强> EDIT_ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ 强>
“精度的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。
答案 2 :(得分:0)
实际上,正如 @Phylogenesis 在第一条评论中所说的那样,当我想到的时候,我们没有卖出足够多的项来溢出double
值的精度,就像物品一样不足以超出float
值的精度。我猜测,我测试并发现如果你运行简单的SELECT SUM(Amount) FROM Invoices
查询,结果将是double
值。但是按照 @Gordon Linoff 的建议,对于强迫症患者最安全的方法是使用强制转换为Decimal
或Currency(Access)
。因此,Access语法中的查询将是:
SELECT SUM(CCur(Price) * Qty)
FROM Invoices;
SELECT SUM(CCur(Amount))
FROM Invoices;
CCur
函数将Single(c# float)
值转换为Currency(c# decimal)
。很高兴知道转换到Double
不是必需的,因为引擎本身就是这样做的。因此,更简单的方法也是安全的,只需运行简单的查询。