找到最接近纬度和经度值的位置
Finding the closest location to a lat and long value
我有两个 tables t1
和 t2
(t1
的大小是 t2
的 1/10)。每个 table 有两列 <Lat, Long>
,其中包含一些点的纬度和经度。对于 t1
中的每一行,我想在 t2
中找到最接近它的那一行。这样做最有效的查询是什么? Hive 是否有任何类型的地理空间搜索库?
你需要做一些触发。
这篇文章
最后一个例程我相信是你要找的(你需要修改它以供使用):
CREATE DEFINER=`root`@`localhost` PROCEDURE closest_restaurants_optimized`
(IN units varchar(5), IN lat Decimal(9,6), IN lon Decimal(9,6),
IN max_distance SMALLINT, IN limit_rows MEDIUMINT)
BEGIN
DECLARE ONE_DEGREE_CONSTANT TINYINT;
DECLARE EARTH_RADIUS_CONSTANT SMALLINT;
DECLARE lon1, lon2, lat1, lat2 float;
IF units = 'miles' THEN
SET ONE_DEGREE_CONSTANT = 69;
SET EARTH_RADIUS_CONSTANT = 3959;
ELSE -- default to kilometers
SET ONE_DEGREE_CONSTANT = 111;
SET EARTH_RADIUS_CONSTANT = 6371;
END IF;
SET lon1 = lon-max_distance/abs(cos(radians(lat))*ONE_DEGREE_CONSTANT);
SET lon2 = lon+max_distance/abs(cos(radians(lat))*ONE_DEGREE_CONSTANT);
SET lat1 = lat-(max_distance/ONE_DEGREE_CONSTANT);
SET lat2 = lat+(max_distance/ONE_DEGREE_CONSTANT);
SELECT pm1.post_id, p.post_title,
ROUND((EARTH_RADIUS_CONSTANT * acos( cos( radians(lat) )
* cos( radians(pm1.meta_value) )
* cos( radians(pm2.meta_value) - radians(lon)) + sin(radians(lat))
* sin( radians(pm1.meta_value)))
), 3) AS distance
FROM goodfood_wp_md20m_postmeta AS pm1,
goodfood_wp_md20m_postmeta AS pm2,
goodfood_wp_md20m_posts AS p
WHERE pm1.meta_key = 'latitude' AND pm2.meta_key = 'longitude'
AND pm1.post_id = pm2.post_id
AND pm1.post_id = p.id
AND p.post_status = 'publish'
AND pm2.meta_value between lon1 and lon2
AND pm1.meta_value between lat1 and lat2
ORDER BY distance ASC
LIMIT limit_rows;
END
我有两个 tables t1
和 t2
(t1
的大小是 t2
的 1/10)。每个 table 有两列 <Lat, Long>
,其中包含一些点的纬度和经度。对于 t1
中的每一行,我想在 t2
中找到最接近它的那一行。这样做最有效的查询是什么? Hive 是否有任何类型的地理空间搜索库?
你需要做一些触发。
这篇文章最后一个例程我相信是你要找的(你需要修改它以供使用):
CREATE DEFINER=`root`@`localhost` PROCEDURE closest_restaurants_optimized`
(IN units varchar(5), IN lat Decimal(9,6), IN lon Decimal(9,6),
IN max_distance SMALLINT, IN limit_rows MEDIUMINT)
BEGIN
DECLARE ONE_DEGREE_CONSTANT TINYINT;
DECLARE EARTH_RADIUS_CONSTANT SMALLINT;
DECLARE lon1, lon2, lat1, lat2 float;
IF units = 'miles' THEN
SET ONE_DEGREE_CONSTANT = 69;
SET EARTH_RADIUS_CONSTANT = 3959;
ELSE -- default to kilometers
SET ONE_DEGREE_CONSTANT = 111;
SET EARTH_RADIUS_CONSTANT = 6371;
END IF;
SET lon1 = lon-max_distance/abs(cos(radians(lat))*ONE_DEGREE_CONSTANT);
SET lon2 = lon+max_distance/abs(cos(radians(lat))*ONE_DEGREE_CONSTANT);
SET lat1 = lat-(max_distance/ONE_DEGREE_CONSTANT);
SET lat2 = lat+(max_distance/ONE_DEGREE_CONSTANT);
SELECT pm1.post_id, p.post_title,
ROUND((EARTH_RADIUS_CONSTANT * acos( cos( radians(lat) )
* cos( radians(pm1.meta_value) )
* cos( radians(pm2.meta_value) - radians(lon)) + sin(radians(lat))
* sin( radians(pm1.meta_value)))
), 3) AS distance
FROM goodfood_wp_md20m_postmeta AS pm1,
goodfood_wp_md20m_postmeta AS pm2,
goodfood_wp_md20m_posts AS p
WHERE pm1.meta_key = 'latitude' AND pm2.meta_key = 'longitude'
AND pm1.post_id = pm2.post_id
AND pm1.post_id = p.id
AND p.post_status = 'publish'
AND pm2.meta_value between lon1 and lon2
AND pm1.meta_value between lat1 and lat2
ORDER BY distance ASC
LIMIT limit_rows;
END