2016-01-19 75 views
-6

當我將數據存儲在變量/列中時,數據精度有問題。SQL Server舍入問題

請看下面的例子

DECLARE @w NUMERIC(38, 15) = 0.458441, 
     @a NUMERIC(38, 15) = 10.000000, 
     @p NUMERIC(38, 15) = 5.000000 

select (1+0.458441)*(1+ 10.000000/100)*(1+ 5.000000/100) 

結果:1.68449935500000000000000000(正確)

SELECT (1 + @w) * (1 + @a/100.0) * (1 + @p/100.0) 

結果:1.684499(不正確)

誰能告訴究竟是什麼原因當我存儲va時近似變量中的變量以及如何修復?

+1

「如何修復?」 - 當您不需要/不需要時,請停止詢問具有較高精度要求的大型數據類型。 –

+0

@Damien_The_Unbeliever - 這些僅僅是我的實時數據非常大的例子。 –

回答

5

首先檢查數據類型:

SELECT '0.458441', system_type_name 
FROM sys.dm_exec_describe_first_result_set(N'SELECT 0.458441', NULL, 0) 
UNION ALL 
SELECT '10.000000', system_type_name 
FROM sys.dm_exec_describe_first_result_set(N'SELECT 10.000000', NULL, 0) 
UNION ALL 
SELECT '5.000000', system_type_name 
FROM sys.dm_exec_describe_first_result_set(N'SELECT 5.000000', NULL, 0); 

╔═══════════╦══════════════════╗ 
║ value ║ system_type_name ║ 
╠═══════════╬══════════════════╣ 
║ 0.458441 ║ numeric(6,6)  ║ 
║ 10.000000 ║ numeric(8,6)  ║ 
║ 5.000000 ║ numeric(7,6)  ║ 
╚═══════════╩══════════════════╝ 

查詢1:

SELECT (1+0.458441)*(1+10.000000/100)*(1+5.000000/100) 
-- 1.684499355 

問題2:

SELECT (1 + CAST(@w AS NUMERIC(8,6))) * 
     (1 + CAST(@a AS NUMERIC(8,6))/100.0) * 
     (1 + CAST(@p AS NUMERIC(8,6))/100.0) 
-- 1.684499355 

SELECT (1 + @w) * (1 + @a/100.0) * (1 + @p/100.0) 
-- 1.684499 

加入鑄造後

LiveDemo

爲什麼是這樣的情況:related article

+1

不錯的一個,我不知道sys.dm_exec_describe dmv.Thanks – TheGameiswar

+0

感謝您的幫助現在我很清楚我的問題。實時任何值都可以到達,這些僅僅是示例。在這種情況下,我怎樣才能使它工作是有一些錯誤的'數字(38,15)' –

+1

重點是,它是**沒有「錯誤」**,因爲你描述它。計算比例/精度的工作方式取決於表達式部分的數據類型。請參閱提到的鏈接。 – lad2025

2

OK,我知道它已經通過它的lad2025..but..only回答一半(至少對我來說)..其唯一的回答如何修復它不是原因..

由於我的好奇心,我做了我自己的研究...在讀谷Precision, Scale, and Length並嘗試一些SQL我發現NUMERIC(p,s)倍增時會產生新的具有新的精度和尺度的數字:

p1 + p2 + 1 
s1 + s2 

近似問題是當P1 + P2 + 1超過38,最大精度SQL Server可以有,精度設定爲38,但所證明下面

規模減少1的發生
DECLARE 
    @a NUMERIC(20, 5) = 0.12345, 
    @b NUMERIC(20, 2) = 0.13, 
    @c NUMERIC(10, 5) = 0.12345, 
    @d NUMERIC(10, 2) = 0.13 

SELECT 0.12345 * 0.13 Result, @a * @b AxB, @c * @d CxD 

結果:

+-----------+----------+-----------+ 
| Result | AxB | CxD | 
+-----------+----------+-----------+ 
| 0.0160485 | 0.016049 | 0.0160485 | 
+-----------+----------+-----------+ 

AXB給錯誤導致其原有的精度LY超過38和CXD給人以21個精密正確的答案,與sys.dm_exec_describe_first_result_set

SELECT '@a * @b', system_type_name 
FROM sys.dm_exec_describe_first_result_set(
    N'DECLARE @c NUMERIC(20, 5) = 0.12345, @d NUMERIC(20, 2) = 0.13 
    SELECT @c * @d', NULL, 0) 
UNION ALL 
SELECT '@c * @d', system_type_name 
FROM sys.dm_exec_describe_first_result_set(
    N'DECLARE @c NUMERIC(10, 5) = 0.12345, @d NUMERIC(10, 2) = 0.13 
    SELECT @c * @d', NULL, 0) 

結果進一步檢查:

+-----------+------------------+ 
| operation | system_type_name | 
+-----------+------------------+ 
| @a * @b | numeric(38,6) | 
| @c * @d | numeric(21,7) | 
+-----------+------------------+ 

下表顯示了@a * @b規模減少。 事情是我不知道這個故意還是一個bug ..