【问题标题】:select within 20 kilometers based on latitude/longitude根据纬度/经度选择20公里以内
【发布时间】:2011-10-18 16:17:59
【问题描述】:

我有一个 mysql 表,其结构如下:

POSTAL_CODE_ID|PostalCode|City|Province|ProvinceCode|CityType|Latitude|Longitude
7|A0N 2J0|Ramea|Newfoundland|NL|D|48.625599999999999|-58.9758
8|A0N 2K0|Francois|Newfoundland|NL|D|48.625599999999999|-58.9758
9|A0N 2L0|Grey River|Newfoundland|NL|D|48.625599999999999|-58.9758

现在我要做的是创建一个查询,该查询将在搜索位置的选定公里范围内选择结果

假设他们搜索“灰色河流”并选择“查找 20 公里内的所有结果”

显然应该选择“灰河”,但也应该根据经纬度选择灰河20公里范围内的所有位置。

我真的不知道该怎么做。我已经阅读了 haversine 公式,但不知道如何将其应用于 mysql SELECT。

任何帮助将不胜感激。

【问题讨论】:

    标签: php mysql select


    【解决方案1】:
    SELECT  *
    FROM    mytable m
    JOIN    mytable mn
    ON      ACOS(COS(RADIANS(m.latitude)) * COS(RADIANS(mn.latitude)) * COS(RADIANS(mn.longitude) - RADIANS(m.longitude)) + SIN(RADIANS(m.latitude)) * SIN(radians(mn.latitude))) <= 20 / 6371.0
    WHERE   m.name = 'grey river'
    

    如果您的表格是MyISAM,您可能希望以原生几何格式存储您的点并在其上创建SPATIAL 索引:

    ALTER TABLE mytable ADD position POINT;
    
    UPDATE  mytable
    SET     position = POINT(latitude, longitude);
    
    ALTER TABLE mytable MODIFY position NOT NULL;
    
    CREATE SPATIAL INDEX sx_mytable_position ON mytable (position);
    
    SELECT  *
    FROM    mytable m
    JOIN    mytable mn
    ON      MBRContains
                    (
                    LineString
                            (
                            Point
                                    (
                                    X(m.position) - 0.009 * 20,
                                    Y(m.position) - 0.009 * 20 / COS(RADIANS(X(m.position)))
                                    ),
                            Point
                                    (
                                    X(m.position) + 0.009 * 20,
                                    Y(m.position) + 0.009 * 20 / COS(RADIANS(X(m.position))
                                    )
                            ),
                    mn.position
                    )
            AND ACOS(COS(RADIANS(m.latitude)) * COS(RADIANS(mn.latitude)) * COS(RADIANS(mn.longitude) - RADIANS(m.longitude)) + SIN(RADIANS(m.latitude)) * SIN(radians(mn.latitude))) <= 20 / 6371.0
    WHERE   m.name = 'grey river'
    

    【讨论】:

    • 为什么要删除所有的 cmets?
    • @Jitamaro:我让他们聊天,因为他们与问题无关。
    • 在你的第二个代码块中,当你使用 MySQL 空间时,为什么不使用 DISTANCE 函数?
    • @Tomas:这样的函数在哪里定义的?
    • @Tomas: dev.mysql.com/doc/refman/5.5/en/gis-class-geometry.html: MySQL 中,SRID 值只是与几何值相关的整数。所有计算均假设欧几里得(平面)几何。无论如何5.0或更高版本不支持此功能。
    【解决方案2】:
    SELECT `s`.suburb_id,`s`.suburb_name,`s`.lat,`s`.long, (((acos(sin(($lat*pi()/180)) * sin((s.lat*pi()/180))+cos(($lat*pi()/180)) * cos((s.lat*pi()/180)) * cos((($long - s.long)*pi()/180))))*180/pi())*60*1.1515*1.609344) AS distance FROM (`mst_suburbs` as s) HAVING distance <= 20 ORDER BY `s`.suburb_id DESC
    

    此查询对我有用,可以获取 12 公里之间的所有经纬度。我有 mst_suburbs 是可能的表,其中有 latlong 列。$lat$long 是我的两个php 变量。我正在传递所需的 lat,long 以从 mst_suburb 获取最近的 12 公里 lat 长列表。您只需要根据您的表格更改列的名称并将经纬度传递给查询即可。

    【讨论】:

      【解决方案3】:

      算法有点复杂,不过here's a link to one solution

      【讨论】:

      • 太棒了!非常感谢你的链接。正是我想要的。
      • 空间索引或空间填充曲线怎么样?
      【解决方案4】:

      您只需使用您的半正弦公式并像这样应用它:

      SELECT   *,
               6371 * ACOS(SIN(RADIANS( $lat1 )) * SIN(RADIANS(`Latitude`)) +
               COS(RADIANS( $lat1 )) * COS(RADIANS(`Latitude`)) * COS(RADIANS(`Longitude`) -
               RADIANS( $lon1 ))) AS `distance`
      FROM     `table`
      WHERE    `distance` <= 20
      ORDER BY `distance` ASC
      

      $lat1$lon1 替换为您要比较的纬度和经度。

      【讨论】:

      • 空间索引或空间填充曲线怎么样?
      • @Jitamaro 怎么样?这是我错过的问题的一部分吗?
      • 如果反对的选民能发表评论,那就太好了。如果你有你的纬度和经度并且想要制定一个在附近搜索的 SQL 查询,这很好用。
      猜你喜欢
      • 2021-09-04
      • 2014-02-18
      • 2010-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多