2016-01-04 100 views
1

對可分數據應用abs時,整數值商被轉換爲十進制數。在應用於可分數據時,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   ConditionValue ConditionRateNbr 
--256.999969482422 9665.77   37.61 

爲什麼會發生這種情況以及如何解決?

+2

什麼是您的數據庫? – Mihai

+0

'ConditionRateNbr'是否需要成爲'真實'?我懷疑你可能使用了「小數」,然後你的分數會達到你所期望的整數值。 – shawnt00

+0

使用二進制浮點類型時的舍入和表示問題。使用4字節類型如REAL會更糟,但DOUBLE會做同樣的事情。此計算在SQLFIddle.com的MySQL 5.5,5.6和SQLite中運行正常,但在PostgreSQL和SQL Server中返回時髦結果。 (甲骨文現在不能工作,但基於我與甲骨文的經驗,我會說它會按預期工作)。不要爲貨幣數量使用二進制浮點值(REAL和DOUBLE數據類型)。在可用的地方使用DECIMAL,NUMBER(在Oracle上)或MONEY。祝你好運。 –

回答

0

我所看到的用錢比小數更可靠。 這是另一個例子。

爲什麼地球上的小數人認爲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 
+1

您沒有爲您的小數值指定比例,因此它基本上被視爲整數。這意味着它在分割前被舍入到2,而3.0/2是1.5。 – shawnt00

1

它與「真實」數據類型是「近似數字」有關,請參閱https://msdn.microsoft.com/en-us/library/ms173773.aspx。我的SQL的知識是不夠深,給予了詳細的解釋,但我有一個解決方案,使用十進制數據類型的I/O實:

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 

IMO它通常是更聰明的使用十進制不是真正避免這種的問題。

1

假設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 

你會看到,除法的結果是realThe ISO synonym for real is float(24).ABS(numeric_expression)函數Returns the same type as numeric_expression.顯然,ABS函數返回默認的float,which is float(53)float(53)包含15位數字,所以你得到15位數字返回。

因此,返回的數據類型不是,因爲您可能會想到,decimal,而是另一個float,默認爲最大大小(可以這麼說)。

如果您將字段定義爲decimals,請參閱here您可能得到的內容。

相關問題