所有点之间的地理距离大于mysql的值

时间:2012-07-21 01:13:02

标签: php mysql math geospatial computational-geometry

从具有纬度和经度的餐馆列表中,如何获得所有这些点之间至少 X km的点?

我的意思是,每家餐厅都没有 X km半径内的任何其他餐厅。

我尝试了下一个查询:

SELECT 
    id,
    lat as x, 
    lng as y,
    concat(ceil((lat+90)/5),',',ceil((lng+180)/5)) as groupParam
FROM 
    restaurants 
GROUP BY groupParam

结果如下:

result of the query

在那个查询中,我按照经纬度和经度进行分组(例如:“12,23”)。所以我只从(lat> = 12&& lat< 13)和(lng> = 23&& lng< 24)得到一个节点。

这很快但不太准确。

谢谢, 威廉·

2 个答案:

答案 0 :(得分:0)

我为一个我写成webapp的hamradio数据库做了一些lon / lat计算: http://dk7sl.de/iRelais

这是select语句,其中$ x和$ y是我的lon / lat坐标。 最大距离设置为15公里。如果您只是删除查询中的“* 1.609344”,则可以切换到里程。此查询选择地理数据表中最近的条目。 Geodata取自http://www.geodatasource.com/world-cities-database/free,在我的mysqldb中包含大约240万条记录。数据库索引是纬度,经度,要素类和要素代码(但这只是因为我按要素类和代码过滤条目)

$ query =“SELECT name,(((ACOS(SIN('。”。$ x。“'* PI()/ 180)* SIN(纬度* PI()/ 180)+ COS(”。$ x 。“* PI()/ 180)* COS(纬度* PI()/ 180)* COS(('”。$ y。“ - 经度)* PI()/ 180))* 180 / PI()) * 60 * 1.1515))* 1.609344 AS distance FROM geodata WHERE feature class ='P'和(feature code ='PPLX'或feature code ='PPL ')HAVING distance< ='15'Order by distance ASC LIMIT 1;“;

也许您可以使用我的select语句并对其进行修改,以便从数据库中获得正确的一组点。

答案 1 :(得分:0)

回答原始问题:

我认为这将为您提供所需的信息:

SELECT DISTINCT
    a.id AS a,
    b.id AS b,
    ACOS(
        SIN(a.lat) * SIN(b.lat) + COS(a.lat) * COS(b.lat) * COS(a.lon - b.lon)
    ) * 6371.01 AS km
FROM 
    restaurants a,
    restaurants b
WHERE
    b.id > a.id AND
    ACOS(
        SIN(a.lat) * SIN(b.lat) + COS(a.lat) * COS(b.lat) * COS(a.lon - b.lon)
    ) * 6371.01 >= X
ORDER BY
    ACOS(
        SIN(a.lat) * SIN(b.lat) + COS(a.lat) * COS(b.lat) * COS(a.lon - b.lon)
    );

其中X是你想要的最小公里数。

不幸的是,这种类型的查询是CROSS JOIN返回Cartesian Product,所以有10家餐馆,你将有36个比较,100个你将有4,851,1,000你将有498,501,等

回答您修改过的问题:

要找到距离任何其他餐厅至少X公里的所有餐厅,请使用:

SELECT
    a.id AS a,
    MIN(ACOS(
        SIN(a.lat) * SIN(b.lat) + COS(a.lat) * COS(b.lat) * COS(a.lon - b.lon)
    ) * 6371.01) AS km
FROM 
    restaurants a,
    restaurants b
WHERE
    b.id > a.id
GROUP BY
    a.id
HAVING
    MIN(ACOS(
        SIN(a.lat) * SIN(b.lat) + COS(a.lat) * COS(b.lat) * COS(a.lon - b.lon)
    ) * 6371.01) >= X
ORDER BY
    MIN(ACOS(
        SIN(a.lat) * SIN(b.lat) + COS(a.lat) * COS(b.lat) * COS(a.lon - b.lon)
    ) * 6371.01)

其中X是你想要的最小公里数。