我目前使用以下格式的MySQL latitude
字段类型存储位置的longitude
和POINT
值:
POINT(51.507351 -0.127758)
我以前从未使用过这种字段类型,因此没有任何查询经验,以及如何实际,有效地使用存储的数据。
我找到了很多链接,演示了搜索指定半径内的项目的各种方法。但是,其中大多数都使用独立的latitude
和longitude
字段,而不是使用MySQL空间字段。
请参阅以下内容:
我正在尝试搜索给定半径内的任何记录(以米为单位)。根据我的表的结构,搜索我的记录并返回指定半径内的任何项目(圆形而非矩形)的最佳,最有效的方法是什么?
这是我到目前为止所做的:
SELECT
*,
(
6373 * acos (
cos ( radians( PASSED_IN_LATITUDE ) )
* cos( radians( X(location) ) )
* cos( radians( Y(location) ) - radians( PASSED_IN_LONGITUDE ) )
+ sin ( radians( PASSED_IN_LATITUDE ) )
* sin( radians( X(location) )
)
) AS distance
FROM locations
HAVING distance < PASSED_IN_RADIUS
我从另一个答案中获取了上述代码,但鉴于这个答案是在2年前发布的,我认为它已经过时了,因此这可能不再是最有效的方法... < / EM>
答案 0 :(得分:1)
假设您在位置上有空间键,您可以执行以下操作:
select * from locations where
contains(geomfromtext('polygon($bounding_rect_coords)'),location)
and earth_distance(location,point($lat,$lon)) < $radius
应使用以下公式计算边界矩形坐标:
$deg_to_rad = $PI/180.0
$rad_to_deg = 1.0/$deg_to_rad
$delta_y = $rad_to_deg *($radius / ($earth_radius * cos($lat*$deg_to_rad))) // the length of the parallel = EARTH_R * cos(lat)
$delta_x = $rad_to_deg * ($radius/$earth_radius)
$x1 = $lat - $delta_x
$x2 = $lat + $delta_x
$y1 = $lon - $delta_y
$y2 = $lon + $delta_y
然后用
获得矩形geomfromtext('polygon(($x1 $y1,$x2 $y1,$x2 $y2, $x1 $y2, $x1 $y1))')
最好在应用程序中卸载数据库服务器。
这个矩形实际上是一个球形矩形,因此在计算中使用PI常量。这个想法很简单。对于给定的并行,将搜索半径转换为经度。这就是我们需要从目标到东部和西部的多少度来覆盖我们的候选点。然后计算相同的纬度 - 与经度不同,这将不依赖于坐标,因为所有经线都具有相同的长度。那就是我们需要向南和向南走多少度。
上述计算假设搜索半径小于并行的长度,例如,对于合理的搜索半径,美国大多数情况都是这种情况,但可能不适用于阿拉斯加的某些地区。因此,最好检查一下(如果delta_y> 90)并相应地剪辑它。你还应该检查你是否正确在北极或南极,事情完全打破了。但希望你的数据没有太多的极地记录。
对于earth_distance()
,您有几种选择:
你的计算本身是好的,即使它已经两年了 - 据我所知,在过去的两年里,只要测量地球上两点之间的距离,就没有发现革命性的东西。
您的原始方法也可以正常工作,但效率低下。 contains
子句的添加允许我们将搜索减少到(希望)相对较小的集合,该集合保证在搜索半径内非常快。然后我们将每个候选人都过滤掉那些没有在earth_distance()
上进行剪辑的人。
我必须添加一个标准免责声明,我将变量插入到可能未经过清理的SQL中。在编写实际生产代码时,请确保验证SQL注入攻击的结果SQL查询。