基于经纬度,在20公里范围内进行选择

8

我可以帮助您翻译以下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中。

任何帮助都将不胜感激。

4个回答

10
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'

你为什么删除了所有评论? - Micromega
1
@Jitamaro: 我把它们转移到聊天中,因为它们与问题无关。 - Quassnoi
@Tomas:这个函数在哪里定义的? - Quassnoi
在MySQL空间中,函数distance已经存在于版本4.1中。 - Tomas
1
@Tomas:http://dev.mysql.com/doc/refman/5.5/en/gis-class-geometry.html:在MySQL中,SRID值只是与几何值相关联的整数。所有计算都假定为欧几里得(平面)几何。无论如何,此函数在5.0或以上版本中均不受支持。 - Quassnoi
显示剩余4条评论

1
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变量,我正在传递所需的经纬度以获取来自mst_suburb的最近12公里经纬度列表。您只需要根据您的表更改列名称并将经纬度传递给查询即可。


0

空间索引或空间填充曲线怎么样? - Micromega

0
你只需要拿出你的哈弗赛恩公式,然后像这样应用它:
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替换为您想要与之比较的纬度和经度。


空间索引或者空间填充曲线怎么样? - Micromega
@Jitamaro 这个怎么样?这是我错过的问题的一部分吗? - deceze
如果投反对票的人能留下评论就好了。如果您拥有纬度和经度,并希望制定一个在附近搜索的SQL查询,那么这个功能可以正常工作。 - deceze

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接