0

从具有纬度和经度的餐厅列表中,我怎样才能获得所有点之间至少有X公里的点?

我的意思是,每家餐厅在X公里半径范围内都没有其他餐厅。

我尝试了下一个查询:

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

结果是这样的:

查询结果

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

那速度很快,但不是很准确。

谢谢,威廉。

4

2 回答 2

0

我为我作为 web 应用程序编写的 hamradio 数据库做了一些 lon/lat 计算:http: //dk7sl.de/iRelais

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

$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.609344distancegeodataWHERE feature class= 'P' AND ( feature code= 'PPLX' OR feature code= 'PPL') HAVING distance<='15' ORDER BY distanceASC LIMIT 1;";

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

于 2012-07-21T01:31:03.340 回答
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 是您希望它们之间的最小公里数。

不幸的是,这种类型的查询是返回笛卡尔 Product的CROSS JOIN,因此对于 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 是您希望它们之间的最小公里数。

于 2012-07-21T01:34:24.130 回答