2014-11-20 48 views
2

當我發現一些奇怪的行爲時,我在SQL Server中執行了一些簡單的財務計算。我試圖將一串數字轉換爲十進制類型。雖然字符串不包含小數點,但我從規範中知道,字符串中的最後3個位置應該在小數點後面。在SQL Server中劃分十進制類型導致不必要的尾隨零

我的第一種方法是有缺陷的,但就這樣的事情:

select convert(decimal(11,3),89456123/1000) as TotalUnits 

這導致89456.000。在投射前進行除法,導致小數部分被截斷。

所以我感動的除法運算中投之外,像這樣:

select convert(decimal(11,3),89456123)/1000 as TotalUnits 

這導致位置的小數點後爆炸。它返回89456.12300000

根據我的十進制規範,我想要11位數字,其中3個小數點後面。現在我總共有13位數字,小數點後面有8位數字。發生了什麼?

爲了得到我想要的東西,我想我必須加倍投,像這樣:

select convert(decimal(11,3), convert(decimal(11,3),89456123)/1000) 

這給89456.123

事實證明,無論我除以什麼,結果小數點爆炸是相同的。該部門是否將數據類型轉換爲雙重或其他?

我的問題是這樣的: 爲什麼會發生這種情況,並且有沒有更好的方法來補償它,而不是雙重鑄造爲十進制。

編輯 我發現這個similar question上如此,但它看起來像他們再次雙擊鑄造。

+0

這適用於RME:'選擇轉換(十進制(11,3),1000分之89456123)' – RBarryYoung 2014-11-20 17:39:08

回答

3

SQL Server會整數運算,以迫使它使用數字,您可以通過1.0

無需使用轉換兩次相乘。這使得89456.123無雙重轉換。

select convert(decimal(11,3),89456123*1.0/1000) as TotalUnits 
+0

答案是正確的,給了+1平衡有人給-1。 – 2014-11-20 17:38:31

+0

在使用這種方法時,我還發現我可以用1000.0除以觸發一個數字結果。 – Slider345 2014-11-24 18:42:05

+0

@ Slider345,是的,你是對的,需要一個數字字段將結果轉換爲數字。 – radar 2014-11-24 18:42:53

2

爲什麼convert(decimal(11,3),89456123)/1000最後有6位小數?規則要求它。 numeric division has rather complicated rules about the resulting type

當你說1.0你最終用最少的比例因子可能一個數字來表示該值:

SELECT SQL_VARIANT_PROPERTY(1.11, 'BaseType') 
SELECT SQL_VARIANT_PROPERTY(1.11, 'Precision') 
SELECT SQL_VARIANT_PROPERTY(1.11, 'Scale') 
SELECT SQL_VARIANT_PROPERTY(1.11, 'TotalBytes') 

你應該怎麼做?由於複雜的規則,我認爲沒有真正優雅的解決方案。我能想到的任何解決方案都涉及到對中間結果的瘋狂類型推斷。我建議非常雷達已經給出了相同的解決方案:

select convert(decimal(11,3), convert(decimal(11, 3), 89456123)/1000) as TotalUnits 

的主要區別是,我認爲作爲一個短手的投*1.0「貓膩」被混淆的代碼的含義。不過,如果你碰巧喜歡它可以隨意使用它。

+1

這正是我想要弄清楚的 - 很好的解釋,+1 – 2014-11-20 19:37:10

0
select convert(decimal(11,3),89456123/CONVERT(decimal(11,3),1000)) 
+0

雖然這段代碼可以解決這個問題,[包括解釋](http://meta.stackexchange.com/questions/114762/explaining-entirely基於代碼的答案)真的有助於提高您的帖子的質量。請記住,您將來會爲讀者回答問題,而這些人可能不知道您的代碼建議的原因。 – gunr2171 2014-11-20 20:46:33

相關問題