Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql lat/lon两个表之间的距离计算_Mysql_Performance_Select_Subquery_Mariadb - Fatal编程技术网

Mysql lat/lon两个表之间的距离计算

Mysql lat/lon两个表之间的距离计算,mysql,performance,select,subquery,mariadb,Mysql,Performance,Select,Subquery,Mariadb,我有下面两张桌子 城市 id,lat,lon 山 id、纬度、经度 SELECT cities.id, (SELECT id FROM mountains WHERE SQRT(POW(69.1 * ( latitude - cities.lat ) , 2 ) + POW( 69.1 * (cities.lon - longitude ) * COS( latitude / 57.3 ) , 2 ) )<20 LIMIT 1) as mounta

我有下面两张桌子

城市 id,lat,lon

山 id、纬度、经度

SELECT cities.id, 
    (SELECT id FROM mountains 
    WHERE SQRT(POW(69.1 * ( latitude -  cities.lat ) , 2 ) + 
    POW( 69.1 * (cities.lon - longitude ) * 
    COS( latitude / 57.3 ) , 2 ) )<20 LIMIT 1) as mountain_id 
FROM cities
使用SELECT本身不是我的问题,但是当我尝试使用给定的结果时。。。e、 g

id mountain_id 

588437 NULL
588993 4269
589014 4201
589021 4213
589036 4952
589052 7625
589113 9235
589125 NULL
589176 1184
589210 4317
…要更新表,一切都变得非常缓慢。我几乎尝试了我所知道的一切。我知道依赖子查询不是最优的,但我不知道如何摆脱它

有没有办法改进我的查询。也许把它改成一个连接

这两个表本身除了纬度和经度之外没有任何共同之处,纬度和经度是不同的,只有在使用计算时才相互关联


MariaDB中的空间距离搜索(km,miles)似乎还不可用。

快速执行此类操作的诀窍是避免对每一对可能的lat/lon点进行所有计算。为此,应合并边界框操作

让我们从使用连接开始。在伪代码中,您需要这样的东西,但如果捕获了一些额外的对,则无所谓,只要它们比其他对相距更远

    SELECT c.city_id, m.mountain_id
      FROM cities c
      JOIN mountains m ON distance_in_miles(c, m) < 20
在此查询中,
20.0
是比较极限半径,
69.0
是定义每纬度法定英里数的常数

然后,在两个表的
(lat、lon、id)
上放置复合索引,您的
JOIN
操作将能够使用索引范围扫描来提高查询效率

最后,您可以在伪代码中使用这些类型的子句来扩充该查询

       ORDER BY  dist_in_miles (c,m) ASC
          LIMIT  1

这里实际上需要使用一个距离公式。你问题中的笛卡尔距离公式是一个近似值,除非你在极点附近,否则效果相当好。您可能需要使用大圆公式来代替。这些被称为球面余弦定律、哈弗森公式或文森特公式。

看起来你想要的是彼此相距20法定英里以内的所有成对(城市/山脉)。对吗?它现在就是这么做的。20英里只是为了减少结果的数量。当我按距离添加顺序时(为了复杂起见,我现在省略了这个顺序),它给出了表1到表2之间最接近的匹配。提前感谢!我试过你的方法。现在看起来慢多了,但我还没有添加所有的过滤器。如何筛选结果以获得每个城市id的一个结果?限制会影响整个结果集。最后,我希望看到一个列表,就像我在原来的帖子中看到的那样,我得到一个城市id和一个山区id。
    SELECT c.city_id, m.mountain_id
      FROM cities c
      JOIN mountains m
                  ON m.lat BETWEEN c.lat - (20.0 / 69.0)
                               AND c.lat + (20.0 / 69.0)
                 AND  m.lon BETWEEN c.lon - (20.0 / (69.0 * COS(RADIANS(c.lat))))
                                AND c.lon + (20.0 / (69.0 * COS(RADIANS(c.lat))))
       ORDER BY  dist_in_miles (c,m) ASC
          LIMIT  1