我正在尝试实施一个"找到最近的位置"从给定的纬度和经度使用mysql。我在wordpress网站上存储了8000个地点。
我设法写了这个:
SELECT
b.ID,
SQRT( POW(69.1 * (b.latitude - 51.5073509), 2) + POW(69.1 * (-0.1277583 - b.longitude) * COS(b.latitude / 57.3), 2)) AS distance
FROM
wp_posts a
LEFT JOIN
(
SELECT
post_id AS ID,
MAX(CASE WHEN meta_key = 'theme_directory_map_latitude' THEN meta_value ELSE NULL END) AS latitude,
MAX(CASE WHEN meta_key = 'theme_directory_map_longitude' THEN meta_value ELSE NULL END) AS longitude
FROM
wp_postmeta
WHERE
meta_key = 'theme_directory_map_latitude' OR meta_key = 'theme_directory_map_longitude'
GROUP BY
post_id
) b ON a.ID = b.ID
WHERE
a.post_type = 'directory'
HAVING
distance < 30
ORDER BY
distance
上面的脚本完成了我需要的东西,但它需要太长时间才能在我的weordpress网站上进行处理,有时甚至会出现超时错误。
在那里,我可以优化上面的代码,以便它运行得更快?
答案 0 :(得分:0)
如果用显式group by
替换join
,这可能会更快。这假设每个帖子最多只有一个纬度和经度:
SELECT b.ID,
SQRT( POW(69.1 * (lat.meta_value - 51.5073509), 2) + POW(69.1 * (-0.1277583 - lng.meta_value) * COS(lat.meta_value / 57.3), 2)) AS distance
FROM wp_posts p JOIN
wp_postmeta lat
on lat.post_id = p.id and lat.meta_key = 'theme_directory_map_latitude'
wp_postmeta lng
on lng.post_id = p.id and lng.meta_key = 'theme_directory_map_longitude'
WHERE p.post_type = 'directory'
HAVING distance < 30
ORDER BY distance;
wp_posts(post_type, id)
上的索引也会有所帮助。与wp_postmeta(post_id, meta_key, meta_value)
上的索引一样。
答案 1 :(得分:0)
我通过创建一个新表来解决我的问题,该表包含我试图从联接解决方案中提取的字段。
SELECT
post_id AS ID,
featured,
IF(latitude <> '', SQRT( POW(69.1 * (latitude - ".$lat."), 2) + POW(69.1 * (".$lng." - longitude) * COS(latitude / 57.3), 2)), '') AS distance
FROM
wp_cbk_location
HAVING
(distance < ".$radius." AND distance <> '') OR featured = 1
ORDER BY
distance
此解决方案已将我的70s查询转换为0.13s,因此我对此解决方案感到满意。
然后我添加了一个post_save动作挂钩来更新wp_cbk_location每次我保存一个帖子所以我创建的新表保持uptodate。
我还有一个问题,我将提交一个新问题。我在post__in中可以拥有的数组中有多少个ID?