我正在尝试使用SQL查询来动态地提取位于城市范围内的事件。我有一个城镇/城市列表,使用Google Geocoding我可以获得每个城市的东北和西南边界。
我看过代码解释了如何检查一个位置(通过lat和long)是否在美国这样的地方的范围内,但我读过这对整个世界都不起作用。
我已经尝试过以下公式,但它似乎不起作用:
AND (
($swLat < $neLat AND lat BETWEEN $swLat AND $neLat)
OR
($neLat < $swLat AND lat BETWEEN $neLat AND $swLat)
AND
($swLng < $neLng AND lng BETWEEN $swLng AND $neLng)
OR
($neLng < $swLng AND lng BETWEEN $neLng AND $swLng)
)
刚刚尝试了下面的第一个建议,这是我得到的输出:
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
INNER JOIN lat_lng_post ON wp_posts.ID = lat_lng_post.post_id
WHERE 1=1
AND wp_posts.ID IN (10027,10095,...,10657)
AND wp_posts.post_type = 'event'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
AND lat_lng_post.lat = lat
AND lat_lng_post.lng = lng
AND (
(
(52.385999 < 52.5688762) AND (lat BETWEEN 52.385999 AND 52.5688762)
OR
(52.5688762 < 52.385999) AND (lat BETWEEN 52.5688762 AND 52.385999)
) AND (
(-2.0174336 < -1.7098294) AND (lng BETWEEN -2.0174336 AND -1.7098294)
OR
(-1.7098294 < -2.0174336) AND (lng BETWEEN -1.7098294 AND -2.0174336)
)
)
ORDER BY wp_posts.post_date DESC
LIMIT 0, 10
编辑2 从barryhunter的回答中,我有一个在查询中调用的函数:
function bounds_query($bounds) {
$swLat = $_SESSION['search']['SW'][0];
$swLng = $_SESSION['search']['SW'][1];
$neLat = $_SESSION['search']['NE'][0];
$neLng = $_SESSION['search']['NE'][1];
$bounds .= ' AND (lat BETWEEN '.$swLat.' AND '.$neLat.')';
if ($neLng < $swLng) {
$bounds .= ' AND NOT (lng BETWEEN '.$neLng.' AND '.$swLng.')';
} else {
$bounds .= ' AND (lng BETWEEN '.$swLng.' AND '.$neLng.')';
}
return $bounds;
}
这将输出以下SQL:
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
INNER JOIN lat_lng_post
ON wp_posts.ID = lat_lng_post.post_id
WHERE 1=1
AND wp_posts.ID IN (10060,10293,...,10657)
AND wp_posts.post_type = 'event'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
AND lat_lng_post.lat = lat
AND lat_lng_post.lng = lng
AND (lat BETWEEN 52.385999 AND 52.5688762) AND (lng BETWEEN -2.0174336 AND -1.7098294)
ORDER BY wp_posts.post_date DESC
LIMIT 0, 10
答案 0 :(得分:1)
问题是当你的BBOX跨越日期时,我在这里注意到:http://sphinxsearch.com/forum/view.html?id=8969与狮身人面像相关,但同样适用于mysql ....
$where = "(lat BETWEEN $swLat AND $neLat)";
if ($neLng < $swLng) {
$where .= " AND NOT (lng BETWEEN $neLng AND $swLng)";
} else {
$where .= " AND (lng BETWEEN $swLng AND $neLng)";
}
使用否定过滤器来排除东西方之间的项目(因为东方longtitde值现在位于globe0的西侧 - 只留下跨越日期线的狭窄停靠点上的结果。
弗兰基虽然你不应该多谈这个问题,因为不应该跨越日期线的任何城市!
(会认为这段代码更干净,因为它避免了对纬度的冗余检查,并将其移动到PHP而不是mysel,但您也可以通过向(lng BETWEEN $neLng AND $swLng)
子句添加NOT逻辑来修复代码)
答案 1 :(得分:0)
在看得太深之前,看起来你错过了OR的一些括号
AND (
(
($swLat < $neLat AND lat BETWEEN $swLat AND $neLat)
OR
($neLat < $swLat AND lat BETWEEN $neLat AND $swLat)
)
AND
(
($swLng < $neLng AND lng BETWEEN $swLng AND $neLng)
OR
($neLng < $swLng AND lng BETWEEN $neLng AND $swLng)
)
)