【问题标题】:Why doesn't this sql query return any results comparing floating point numbers?为什么这个 sql 查询不返回任何比较浮点数的结果?
【发布时间】:2012-02-09 00:00:54
【问题描述】:

我在 mysql 表中有这个:

idbolag_idintlatlngitudedouble

如果我使用lngitude 列,则不会返回任何结果:

lngitude查询: SELECT * FROM location_forslag WHERElngitude= 13.8461208

但是,如果我使用 lat 列,它确实返回结果:

lat查询: SELECT * FROM location_forslag WHERElat= 58.3902782

lngitude 列有什么问题?

【问题讨论】:

  • 试试WHERE lngitude BETWEEN 13.8461208 AND 13.8461209
  • @Benoit 如果我将其更改为 13.8461207 AND 13.8461208 则可以工作

标签: mysql double


【解决方案1】:

=等于运算符比较浮点数通常不是一个好主意。

对于您的应用程序,您需要考虑您希望答案有多接近。

1 度约 112 公里,0.00001 度约 1.1 米(在赤道处)。如果两点相差 0.00000001 度 = 1mm,您真的希望您的应用程序说“不相等”吗?

set @EPSLION = 0.00001  /* 1.1 metres at equator */

SELECT * FROM location_forslag 
WHERE `lngitude` >= 13.8461208 -@EPSILON 
AND `lngitude` <= 13.8461208 + @EPSILON

这将返回 lngitude 在所需值的@epsilon 度范围内的点。 您应该为 epsilon 选择一个适合您的应用程序的值。

【讨论】:

  • 在这种情况下使用 SQL BETWEEN 关键字还不错(IMO 更具可读性)。
  • 使用lngitude LIKE 13.8461208怎么样?有没有办法解决?
  • @Lille_skutt:不,你必须慎重决定你想要什么样的准确性,并明确地进行比较。数据库在这里没有任何帮助 - 除非您安装了一些 GIS 扩展。
  • @Ben Okey,但我觉得这很奇怪,你不能将一个数字与完全相同的数字进行比较。 mysql-database最多可以优惠多少?我发送给它的值将始终与其中存储的值完全相同。
  • @这不是完全相同的数字。 13.8461208 可能不是二进数(以 2 为底数没有有限表示),因为 1/3 不是十进制数。当计算机将二进制格式存储的内容转换为十进制表示时,当您将此基于 10 的表示返回给计算机时,让他将 ni 以 2 为底进行转换,可能会损失精度。
【解决方案2】:

Floating points are irritating....

 WHERE ABS(lngitude - 13.8461208) < 0.00000005

【讨论】:

  • 确实有效。所以它与其他专栏合作只是一个巧合?我可以将其存储在更好的数据类型中吗?
  • A DECIMAL 数据类型在最近的 MySQL 版本中是准确的,请参阅链接。
  • 数据类型很好,问题是“相等”的含义取决于应用程序 - 在现实世界中没有这样的事情。在卫星导航应用程序中,equal 可能是“10 米内”。对于“0.05 米以内”的土地注册数据库可能就足够了。建厨房,可能是“5毫米以内”。
  • @Wrikken:这可能会阻止使用索引。
  • @Ben:好点。虽然写我的方式更短,但你的方式可以使用索引,老实说,查询很可能会运行更多次,然后编写代码(如果操作正确,只会运行一次;))
【解决方案3】:

将浮点数转换为十进制以进行比较。我遇到了同样的问题并这样解决:

SELECT
    [dbo].[Story].[Longitude],
    [dbo].[Story].[Latitude],
    [dbo].[Story].[Location],
FROM
    [dbo].[Story],
    [dbo].[Places]
WHERE
    convert(decimal, [dbo].[Story].[Latitude]) = convert(decimal,  [dbo].[Places].[Latitude])
    and
    convert(decimal, [dbo].[Story].[Longitude]) = convert(decimal, [dbo].[Places].[Longitude])
    and
    [dbo].[Places].[Id] = @PlacesID 
    and
    [dbo].[Story].IsDraft = 0
ORDER BY
    [dbo].[Story].[Time] desc

查看 WHERE 分句后的前 3 行。 希望对您有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-27
    • 1970-01-01
    相关资源
    最近更新 更多