SQL查找属于圆

时间:2015-09-06 20:09:47

标签: mysql sql jpa math spring-boot

我有一个SQL数据库集合,我为其分配了坐标(lat,long)。我想问一下距离我内心5公里范围内的那些点。我想知道如何以不收集不必要记录的方式构造查询?

2 个答案:

答案 0 :(得分:2)

由于你所说的距离约为5公里,我们可能不在北极或南极附近,我们可以使用近似的经度和纬度值网格系统。 latidude中的每个学位相当于km_per_lat=6371km*2*pi/360degrees = 111.195km的距离。相隔1度的两条纵向线之间的距离取决于实际纬度:

km_per_long=km_per_lat * cos(lat)

对于德国北部(北纬51度)的地区,这个值约为69.98公里。

因此,假设我们对lat0和long0周围的小距离感兴趣,我们可以安全地假设纵向和纬度角的平移因子将保持不变,我们可以简单地应用公式

SELECT 111.195*sqrt(power(lat-@lat0,2)
                   +power(cos(pi()/180*@lat0)*(long-@long0),2)) dist_in_km FROM tbl

由于您要在选择的WHERE子句中使用公式,因此可以使用以下内容:

SELECT * FROM tbl 
WHERE 111.195*sqrt(power(lat-@lat0,2)
                  +power(cos(pi()/180*@lat0)*(long-@long0),2)) < 5

select语句适用于以度数(十进制表示法)给出的纬度和经度值。因此,我们必须将cos()函数中的值转换为弧度,方法是将其与pi()/180相乘。

如果你必须使用更远的距离(> 500km),那么最好应用导航中使用的适当距离公式,如

cos(delta)=cos(lat0)*cos(lat)*cos(long-long0) + sin(lat0)*sin(lat)

通过应用acos()计算实际角度增量后,您只需将该值乘以地球的半径R = 6371km = 180/pi()*111.195km即可得到所需距离(请参阅此处:Wiki: great circle distance

更新(回复评论):

不确定你打算做什么。如果您只想比较一个参考位置,那么您当然可以预编译距离计算有点像

SELECT @lat0:=51,@long0:=-9;  -- assuming a base position of: 51°N 9°E
SELECT @rad:=PI()/180,@fx:=@rad*6371,@fy:=@fx*cos(@rad*@lat0);

您的距离计算将简化为

SELECT @dist:=sqrt(power(@fx*(lat-@lat0),2)+power(@fy*(long-@long0),2))

当前位置在latlong(不再需要余弦函数)。是否要首先在数据库中存储所有传入的位置,或者是否要在Spring,Java或您正在使用的任何语言之外的某个位置进行计算,由您决定。方程式就在那里,易于使用。

答案 1 :(得分:-1)

我会和Euklid一起去。 dist=sqrt(power(x1-x2,2)+power(y1-y2,2))。它无处不在。也许您必须添加转换为x / y坐标,如果度数不能以km为单位进行平移。

你可以去选择你喜欢的一切WHERE x IS BETWEEN (x-5) AND (x+5) AND y IS BETWEEN (y-5) AND (y+5)。现在您可以使用Euklid查看结果。

通过优化结果顺序,您可以首先获得更好的结果。也许有一种方法可以将Euklid带到SQL中。