2014-03-06 61 views
4

我將示例更改爲使用FLOAT ......太多人都掛在整個NVARCHAR的東西上。我們不把數字作爲NVARCHAR存儲在數據庫中。我只是以NVARCHAR爲例。我用FLOAT得到了同樣的結果。SQL Server ROUND()不適用於以1結尾的FLOAT

我們遇到與SQL Server的ROUND)的一些FLOAT的

 
    DECLARE @EXCHANGE_RATE FLOAT 
    SET @EXCHANGE_RATE = 1.327810000000000000000 
    SELECT ROUND(@EXCHANGE_RATE,6,1) 
    SET @EXCHANGE_RATE = 1.327820000000000000000 
    SELECT ROUND(@EXCHANGE_RATE,6,1) 

首先一個問題(返回:1.327809 第二個返回:1.32782

你會第一個想到的會返回1.32781,而不是1.327809。

這是ROUND中的一個功能或錯誤嗎?任何簡單的方法呢?

謝謝!

基於鑄造他們爲十進制的墊的想法,這個工程......這是醜陋的,但工程。我使用10的原因是,我查看了我們的數據庫,這似乎是我們存儲的最長的數字。此外,我需要將其轉換回FLOAT,因爲他們不希望看到任何尾隨0的

 
    DECLARE @EXCHANGE_RATE FLOAT 
    SET @EXCHANGE_RATE = 1.327810000000000000000 
    SELECT CAST(ROUND(CAST(@EXCHANGE_RATE AS DECIMAL(28,10)),6,1) AS FLOAT) 

回答

0

我將離開這裏之下的那一刻,這是事實,但它不是爲原因op的問題。
正確的答案是由MatBailie提供的一個,-the NVARCHAR字符串被轉換爲一個浮子,然後截斷操作被減少它到下一個較低值...

從MSDN爲Round function

函數
是要執行的操作的類型。函數必須是tinyint,smallint或int。當省略函數或值爲0(默認值)時,numeric_expression將被舍入。 。*當指定除0以外的值,數值_表達式被截斷*

嘗試此,它顯示的區別:

DECLARE @EXCHANGE_RATE NVARCHAR(200) 
SET @EXCHANGE_RATE = '1.3278100' 
SELECT ROUND(@EXCHANGE_RATE,6,0) Rounded, 
     ROUND(@EXCHANGE_RATE,6,1) Truncated 

SET @EXCHANGE_RATE = '1.327810000001' 
SELECT ROUND(@EXCHANGE_RATE,6,0) Rounded, 
     ROUND(@EXCHANGE_RATE,6,1) Truncated 

輸出類型由輸入確定...在這種情況下,輸入是'1.3278100',因此該值被轉換爲數字數據類型,其精度基於字符串中有效數字的數量('1.3278100'有5位有效數字),因此輸出類型被確定爲數字( 6,5)或類似的東西......這會導致意外的截斷。這已經讓我咬傷了。

+0

那麼1.3278100截斷是1.327809?這對我來說似乎不太合適......這就像說100和90一樣。 – kschlege

+0

我得到1.327809,和他們說的第一個例子 –

+0

一樣,你覺得這樣做對嗎? – kschlege

0

使用ROUND(@var,6)而不是ROUND(@var,6,1)。在ROUND()函數中有第三個可選參數,看起來你在這裏不需要它。

+0

我確實需要它,他們希望值被截斷,而不是四捨五入。一些FLOAT的超過6位數字。 例如,他們希望1.3278839999999被截斷爲1.327883,而不是1.327884 – kschlege

+0

哦,我看到了,我在編輯它之前發現了您的問題,看起來像 –

+0

不,我不清楚他們希望數字被截斷,而不是四捨五入。 :) – kschlege

2

試試這個查詢。

SELECT 
    ROUND('1.3278100',6,0)      AS x0, 
    ROUND('1.3278200',6,0)      AS y0, 
    ROUND('1.3278100',6,1)      AS x1, 
    ROUND('1.3278200',6,1)      AS y1, 

    ROUND(CAST('1.3278100' AS FLOAT), 6, 0) AS a0, 
    ROUND(CAST('1.3278200' AS FLOAT), 6, 0) AS b0, 
    ROUND(CAST('1.3278100' AS FLOAT), 6, 1) AS a1, 
    ROUND(CAST('1.3278200' AS FLOAT), 6, 1) AS b1, 

    ROUND(CAST('1.3278100' AS DECIMAL(9,8)), 6, 0) AS i0, 
    ROUND(CAST('1.3278200' AS DECIMAL(9,8)), 6, 0) AS j0, 
    ROUND(CAST('1.3278100' AS DECIMAL(9,8)), 6, 1) AS i1, 
    ROUND(CAST('1.3278200' AS DECIMAL(9,8)), 6, 1) AS j1 
; 

http://sqlfiddle.com/#!6/d41d8/15607

這一點讓我的是,ROUND()被隱式截斷之前您鑄造VARCHARFLOAT

而作爲FLOAT不能準確代表1.327810,你實際上截斷1。3278099999999(或類似的東西)。

因此,簡而言之,在截斷之前明確地將它們轉換爲DECIMAL。或者根本不要將數字數據存儲爲字符串...

+0

我試過了,但是當投射到DECIMAL時,我得到0的尾隨。然後,我必須嘗試擺脫它們......如果必須的話,那就是我必須要做的。數據庫中的所有值都以FLOAT的形式存儲,但我得到的結果與NVARCHAR相同,這就是爲什麼我以此爲例。 – kschlege

+0

當我查看數據庫中的值時,它是FLOAT,它是1.32781。當我從數據庫中選擇它時,它是1.32781。當我嘗試在ROUND()中使用它時,M $認爲它是1.327809999999999999。 – kschlege

+0

This works ...這是醜陋的,但作品

 SELECT CAST(ROUND(CAST(@MY_FLOAT AS DECIMAL(18,8)),6,1) AS FLOAT) 
kschlege