有人可以帮助我理解为什么使用where
搜索Float匹配的工作方式如下:
> latitude = 37.9763
37.9763
> Branch.first.latitude
# Branch Load (0.4ms) SELECT `branches`.* FROM `branches` ORDER BY `branches`.`id` ASC LIMIT 1
37.9763
> Branch.first.latitude.class
Float < Numeric
> latitude.class
Float < Numeric
> Branch.where(latitude: latitude)
# Branch Load (11.7ms) SELECT `branches`.* FROM `branches` WHERE `branches`.`latitude` = 37.9763
[]
我还尝试了Branch.where("latitude = ?", latitude)
,但获得了[]
我一定是在失去理智。
> Branch.where('latitude = ?', Branch.first.latitude)
# Branch Load (0.4ms) SELECT `branches`.* FROM `branches` ORDER BY `branches`.`id` ASC LIMIT 1
# Branch Load (11.3ms) SELECT `branches`.* FROM `branches` WHERE (latitude = 37.9763)
[]
对于任何好奇的人,我只能使用以下内容在2000个分支中找到3个no match
个案例来查找重复项
hash = Branch.group(:business_name, :latitude, :longitude).count
hash.select{|k,v| v > 1}.each do |groupings, count|
business_name = groupings[0]
latitude = groupings[1]
longitude = groupings[2]
branches = Branch.where(
business_name: business_name,
latitude: (latitude - 0.0001)..(latitude + 0.0001),
longitude: (longitude - 0.0001)..(longitude + 0.0001)
)
puts "#{business_name} Count = #{count}"
puts "#{business_name} Branch Count = #{branches.count}"
puts "no match" if count != branches.count
end
答案 0 :(得分:1)
由于floating point numbers are represented的原因,可能会发生这种情况。通过使用正常的相等比较,无法可靠地比较它们。而不是检查完全匹配,最好在比较它们之前检查数字是否在一个范围内或将两个数字四舍五入到一定的精度。
关于具有地理坐标的特定示例(我假设这是因为使用了latitude
),我建议使用decimal
列类型而不是float
。
如果您想坚持float
列,我可以建议检查值是否在某个范围内,例如:
Branch.where("latitude > ? AND latitude < ?", latitude - 0.00001, latitude + 0.00001)
或
Branch.where(latitude: (latitude - 0.00001)..(latitude + 0.00001))