2015-11-06 111 views
4

我想查詢一個數據庫,我需要得到一個其權重等於60.5的客戶列表。問題是60.5是一個真正的我從來沒有在where子句之前用真正的查詢數據庫。WHERE子句中的SQL Server浮點數

我已經試過這樣:

SELECT Name FROM Customers WHERE Weight=60.5 
SELECT Name FROM Customers WHERE Weight=cast(60.5 as real) 
SELECT Name FROM Customers WHERE Weight=cast(60.5 as decimal) 
SELECT Name FROM Customers WHERE Weight=convert(real,'60.5') 
SELECT Name FROM Customers WHERE Weight=convert(decimal,'60.5') 

這些查詢返回0值,但在Customers表中的10個行與重量= 60.5

+0

「Weight」列的確切類型是什麼? –

+0

列重量的確切類型是真實的。 – userfloflo

+0

如果您運行'SELECT WHERE Weight BETWEEN 60和61'的客戶,您會得到什麼?使用real或float的原因很少。除非這是航天飛機的申請,否則真實絕對不是人體重量的候選人。用十進制(19,2)代替 –

回答

11

您的問題是浮點數被定義不準確。將60.5與60.5比較看起來可能不如你注意到的那樣。

一個典型的解決方案是測量兩個值之間的差額,如果它的體積更小,然後一些預定義的ε,等於承認它們爲:

SELECT Name FROM Customers WHERE ABS(Weight-60.5) < 0.001 

爲了獲得更好的性能,你其實應該使用:

SELECT Name FROM Customers WHERE Weight BETWEEN 64.999 AND 65.001 
+1

這可以通過使用範圍謂詞來改變。 –

+0

@MartinSmith - 同意! – Amit

-2

問題是real是一個近似值。肯定會出現輕微的舍入誤差,意思是60.5!= 60.50000001。 MSSQL文檔警告此

用於浮點數字的近似數字數據類型 數據。浮點數據是近似的;因此,不是所有的值 數據類型範圍可以準確地 (https://msdn.microsoft.com/nl-nl/library/ms173773.aspx)表示

可能的解決方法是向列轉換爲字符串,並比較='60.5'。 @Amit的解決方案也非常流暢;不需要轉換。

+0

不會將實數轉換爲字符串會導致包含所有數字的字符串?例如。 ''60 .50000001''。 –

+0

格式不正確時未使用。從我的答案中鏈接的同一頁面:'當您想從浮點數或實數轉換爲字符數據時,使用STR字符串函數通常比CAST()更有用。這是因爲STR可以更好地控制格式.' – steenbergh

+0

如何處理像'60.499999999'這樣的精度錯誤? –

2

如果您需要平等比較,您應該將列的類型更改爲DECIMAL。十進制數字存儲和精確比較,而實數和浮點數字是近似值。

@Amit的答案會有效,但與我的方法相比,它的表現會很差。 ABS(Weight-60.5) < 0.001無法使用索引查找。但是,如果您將列轉換爲DECIMAL,那麼Weight=60.5將表現良好並使用索引查找。

+0

不知道爲什麼這是downvoted。 –

+0

我認爲這是一個有用的一般建議,但不一定適用於此處(或其他地方)。 – Amit

+0

我在+1陣營,但我必須驚呼並說我不喜歡「競技風格」。 – Amit