WHERE子句中的SQL Server浮点数

问题描述:

我想查询一个数据库,我需要得到一个其权重等于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)代替 –

您的问题是浮点数被定义不准确。将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

问题是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'这样的精度错误? –

如果您需要平等比较,您应该将列的类型更改为DECIMAL。十进制数字存储和精确比较,而实数和浮点数字是近似值。

@Amit的答案会有效,但与我的方法相比,它的表现会很差。 ABS(Weight-60.5) < 0.001无法使用索引查找。但是,如果您将列转换为DECIMAL,那么Weight=60.5将表现良好并使用索引查找。

+0

不知道为什么这是downvoted。 –

+0

我认为这是一个有用的一般建议,但不一定适用于此处(或其他地方)。 – Amit

+0

我在+1阵营,但我必须惊呼并说我不喜欢“竞技风格”。 – Amit