SQL ABS()在应用于可整除数据时返回意外的十进制数

SQL ABS()在应用于可整除数据时返回意外的十进制数,sql,Sql,在可除数据上应用abs时,整数商被转换为十进制 create table #data ( ConditionValue money, ConditionRateNbr real) insert into #data values(9665.77,37.61) select abs(conditionvalue/conditionrateNbr) Using_Abs ,* from #data --Using_Abs

在可除数据上应用abs时,整数商被转换为十进制

create table #data ( ConditionValue money, ConditionRateNbr real)
              insert into #data values(9665.77,37.61)
              select abs(conditionvalue/conditionrateNbr) Using_Abs ,* 
         from #data

--Using_Abs         ConditionValue  ConditionRateNbr
--256.999969482422  9665.77         37.61
为什么会发生这种情况以及如何解决?

这与“真实”数据类型是“近似数”有关,请参阅。我对SQL的了解不够深入,无法给出详细的解释,但我确实有一个解决方案,使用十进制数据类型I/o real:

create table #data ( ConditionValue money, ConditionRateNbr decimal(38,20))
              insert into #data values(9665.77,37.61)
              select abs(conditionvalue/conditionrateNbr) Using_Abs ,* 
         from #data

在我看来,使用十进制通常比使用实数更明智,以避免此类问题。

假设使用sql server,但如果运行以下脚本:

CREATE TABLE #data
(
    ConditionValue MONEY
,   ConditionRateNbr REAL
)
INSERT  INTO #data
VALUES  ( 9665.77, 37.61 )

SELECT  *
INTO data
FROM    (
SELECT  ABS(ConditionValue / ConditionRateNbr) Using_Abs
,       conditionValue / ConditionRateNbr test
,       *
FROM    #data
)a

SELECT * FROM INFORMATION_SCHEMA.COLUMNS AS C WHERE C.TABLE_NAME = 'data'

DROP TABLE #data
DROP TABLE data
您将看到除法的结果是一个
实数
ABS(数值表达式)
函数显然,
ABS
函数返回默认的
float
float(53)
包含15位数字,因此返回15位数字

因此,返回的数据类型并不像您最初认为的那样是一个
十进制
,而是另一个
浮点
,默认为其最大大小(可以这么说)


如果您将字段定义为小数,请查看可能得到的结果。

我所看到的使用货币比使用小数更可靠。 这里是另一个例子

我不知道到底为什么十进制数把3/1.5看成1.5

declare @real real = 1.5, @realup money=3
select @realUp numerator, @real denominator, @realup /cast (@real as money) money, @realup /cast(@real as decimal) decimal

--numerator denominator money   decimal
--3.00      1.5         2.00    1.50000000000000000000000

你的数据库是什么?是否需要是真实的?我怀疑您可能使用了一个
十进制
,然后您的除法将得到您期望的整数值。使用二进制浮点类型时,舍入和表示问题。如果使用4字节类型(如REAL),情况会更糟,但DOUBLE也会这样做。此计算在SQLFIddle.com上的MySQL 5.5、5.6和SQLite中运行正常,但在PostgreSQL和SQL Server中返回时髦的结果。(甲骨文目前不工作,但根据我与甲骨文的经验,我会说它会按预期工作)。永远不要对货币量使用二进制浮点值(实数和双精度数据类型)。使用十进制、数字(在Oracle上)或货币(如果可用)。祝你好运。你没有为十进制值指定小数位数,所以它基本上被视为整数。这意味着在除法之前它被四舍五入到2,3.0/2是1.5。