因此,我具有此功能,可以根据纬度,经度和半径参数来计算最近的城市。
DELIMITER $$ DROP PROCEDURE IF EXISTS `world_db`.`geolocate_close_cities`$$ CREATE PROCEDURE `geolocate_close_cities`(IN p_latitude DECIMAL(8,2), p_longitude DECIMAL(8,2), IN p_radius INTEGER(5)) BEGIN SELECT id, country_id, longitude, latitude, city, truncate((degrees(acos( sin(radians(latitude)) * sin(radians(p_latitude)) + cos(radians(latitude)) * cos(radians(p_latitude)) * cos(radians(p_longitude - longitude) ) ) ) * 69.09*1.6),1) as distance FROM cities HAVING distance < p_radius ORDER BY distance desc; END$$ DELIMITER ;
这是我的城市表的结构:
> +------------+-------------+------+-----+---------+----------------+ | > Field | Type | Null | Key | Default | Extra | > +------------+-------------+------+-----+---------+----------------+ | > id | int(11) | NO | PRI | NULL | auto_increment | | > country_id | smallint(6) | NO | | NULL | | | > region_id | smallint(6) | NO | | NULL | | | > city | varchar(45) | NO | | NULL | | | > latitude | float | NO | | NULL | | | > longitude | float | NO | | NULL | | | > timezone | varchar(10) | NO | | NULL | | | > dma_id | smallint(6) | YES | | NULL | | | > code | varchar(4) | YES | | NULL | | > +------------+-------------+------+-----+---------+----------------+
效果很好。
我想做的(伪代码)是这样的:
SELECT * FROM cities WHERE DISTANCE(SELECT id FROM cities WHERE id={cityId}, {km))
它将返回我最近的城市。
关于如何执行此操作的任何想法?
此刻,我只是调用函数,然后将id遍历到数组中,然后在city表中执行WHEREIN,这显然不是很有效。
任何帮助深表感谢。谢谢。
如果您可以限制城市与当地位置之间的最大距离,请利用纬度一分钟(北-南)一海里这一事实。
在您的纬度表上放置一个索引。
根据问题中显示的Haversine公式,使自己成为haversine(lat1,lat2,long1,long2,unit)存储的函数。见下文
然后,根据已知的纬度,经度和公里数,执行此操作。
SELECT * from cities a where :mylatitude >= a.latitude - :mykm/111.12 and :mylatitude <= a.latitude + :mykm/111.12 and haversine(:mylatitude,a.latitude,:mylongitude,a.longitude, 'KM') <= :mykm order by haversine(:mylatitude,a.latitude,:mylongitude,a.longitude, 'KM')
这将使用纬度边界框粗略地排除距离您的地点太远的城市。DBMS将在纬度索引上使用索引范围扫描,以快速挑选出城市表中值得考虑的行。然后它将运行您的Haversine函数,该函数具有所有正弦和余弦数学,仅在这些行上。
我建议使用纬度,因为经度在地面上的距离会随纬度而变化。
请注意,这是粗略的。这对于找店员很好,但是如果您是土木工程师,则不要使用它-地球呈椭圆形,并且假设它是圆形的。
(对不起,111.12幻数。这是纬度中的公里数,即60海里。)