【问题标题】:how to get nearest value from database in mysql如何从mysql中的数据库中获取最接近的值
【发布时间】:2011-11-08 07:32:27
【问题描述】:

我正在使用mySQLCodeIgniter。我的数据库中有一些浮点数,例如

  • 8.3456
  • 8.5555
  • 4.5556

我想……

SELECT * FROM table WHERE value = $myvalue

但我不能在我的 SELECT 查询中使用value = $myvalue,因为$myvalue 不完全等于数据库值。我需要从数据库中获取最接近 $myvalue 的值。

如果$myvalue 是5,我想选择值4.5556

如何在 mySQL 中执行此操作?

【问题讨论】:

  • 如果您有几行,那么顶部的答案就足够了 - 但是如果您有数百万行,我不会推荐它们,因为它们会扫描整个表格 - 而是在底部(权衡是可读性,因为查询更长 - 但也更快)

标签: mysql sql codeigniter select


【解决方案1】:
select * 
from table 
order by abs(value - $myvalue)
limit 1

【讨论】:

  • 可能会进行(慢)表扫描。
【解决方案2】:

假设您有 10% 的容差 (+/-),您可以尝试以下方法:

select * from table 
where value >= ($myvalue * .9) and value <= ($myvalue * 1.1) 
order by abs(value - $myvalue) limit 1

略微更新了从其他人那里窃取的信息 - 这应该会返回假设容差范围内最接近的结果。 (另外,我刚刚注意到哪里不正确,抱歉 - 现在应该可以了)。

【讨论】:

  • 如果最近的 $myvalue 与任意值的距离大于您的任意 % 怎么办?
  • 原来的要求不是很清楚。当然,如果没有“可接受的范围”,您可以说 10000000000 足够接近“1”,假设您的数据库中没有更好的东西。在这种情况下,您可以删除“where”部分。
  • 注意,如果$Myvalue为0,这将失败。如果你真的想这样做,你需要添加OR (($myvalue &gt;= (value * .9)) AND ($myvalue &lt;= (value * 1.1)))
  • 例如,如果他输入 6,这将不会显示最接近的值 -> 但是您使用 >= 和 任何看到这个的人请看我的答案底部,这将给出一个快速、正确的结果。
【解决方案3】:
(
select   *
from     table
where    value >= $myvalue
order by value asc
limit 1
)
union
(
select   *
from     table
where    value < $myvalue
order by value desc
limit 1
)
order by abs(value - $myvalue)
limit 1

这可能看起来违反直觉,但速度会比目前显示的其他查询更快。

这是因为greater thanless than 查询更快。

然后在两个值上执行ABS 没什么。

这将在我能想到的单个查询中为您提供最快的返回。

对整个表执行ABS 会很慢,因为它会扫描整个表。

【讨论】:

  • 看起来是迄今为止最好的答案
【解决方案4】:

获取类似于$val的最大值:

SELECT * FROM tab WHERE val <= $val ORDER BY val DESC LIMIT 1

获取类似于$val的最小值:

SELECT * FROM tab WHERE val >= $val ORDER BY val LIMIT 1

在任一方向上获取类似于 $val 的最接近的值:

SELECT * FROM tab ORDER BY abs(val - $val) LIMIT 1

【讨论】:

    【解决方案5】:

    从以下取第一个值:

    select * from table order by abs(value - $myvalue);
    

    【讨论】:

      【解决方案6】:

      就我而言,我使用浏览器的地理位置并尝试根据我在表格中的坐标找到最近的城市/州。

      表结构:

      id    zipcode    city_state   lat    lon
      1     12345      Example, GA  85.3   -83.2
      

      建议在使用之前对其进行大力测试——可能需要一些调整,但我想以此作为开始

      SELECT city_state, 
         zipcode, 
         ( Abs( lat - -33.867886 ) 
           + Abs( lon - -63.987) ) AS distance
      FROM   zipcodes 
      ORDER  BY distance 
      LIMIT  1;  
      

      对于 laravel 用户:

      $city = Zipcodes::selectRaw
          ('city_state, zipcode,  ( ABS( lat - ? ) + ABS( lon - ?) ) AS distance', [$lat, $lon])
              ->orderBy('distance')
              ->first();
      
      echo $city->city_state
      

      希望有一天这对某人有所帮助。

      【讨论】:

        【解决方案7】:
        SELECT * FROM table1 ORDER BY ABS(value - '$myvalue') LIMIT 1 
        

        【讨论】:

          【解决方案8】:

          不幸的是,我认为您的数据库可能会对涉及abs 的解决方案进行全表扫描,因此一旦您的表增长,它们将(非常)慢。可以在此earlier thread 中找到快速运行的解决方案。

          【讨论】:

            【解决方案9】:
            SELECT number, ABS( number - 2500 ) AS distance
            FROM numbers
            ORDER BY distance
            LIMIT 6
            

            Selecting closest values in MySQL

            【讨论】:

              【解决方案10】:

              试试这个:

              SELECT *,abs((columnname -Yourvalue)) as near
                FROM table
               WHERE order by near limit 0,1
              

              【讨论】:

                【解决方案11】:

                阅读此页http://dev.mysql.com/doc/refman/5.1/en/mathematical-functions.html#function_round

                但您的选择看起来像这样

                select value from table where ROUND(value) = $myvalue 
                

                【讨论】:

                • 如果最近的$myvalue与任何值的距离大于1怎么办?
                • @Bohemian - 在某些时候你需要一个截止点来匹配值
                • @Bohemian,不,这完全取决于您的应用程序,如果您需要一个截止值,它应该始终是原始值的百分比。如果您不处理8.12,而是处理15,481,254,454,875,544,545.1,该怎么办?
                • 问题很明确:“选择最接近的值”。它没有说明值的多远......可能是1000。你的答案很简单,“错误”。
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-07-30
                • 2020-10-30
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多