获取落在从数据库中标记半径范围内的结果(Get results that fall within m

2019-06-17 12:44发布

更新2012年11月16日

我想再次提出这个问题,有一个坚实的,很好地解决了新的赏金提供。 看来,只有解决方案( shubhansh的回答 )没有有效地现在的工作。 我会解释为什么。

首先,这是现场地图我有半径和人民,半径是red和人民都在blue

正如你所看到的,有two人在这个地图eight半径,基本上我只得到这是个人Person A ,但我没有得到Person B ,我猜的SQL不正确捡起来这我需要的是从人的半径和标记半径精准。

它看起来像什么拾取的是半径,而不是那些谁重叠的范围内,我需要它能够拿起任何结果互相重叠的任何半径。

我要寻找比shubhansh的答案准确和精确地SQL。 您可以在下面阅读阅读我究竟需要查询采取行动,拿起准确的人。

这些数据, 人们

+-----------+-----------+--------+
| latitude  | longitude | radius |
+-----------+-----------+--------+
| 51.517395 | -0.053129 | 5.6    |
| 51.506607 | -0.116129 | 0.7    |
+-----------+-----------+--------+

请注意, radius为公里。

+-----------+-----------+-----+
| latitude  | longitude | km  |
+-----------+-----------+-----+
| 51.502117 | -0.103340 | 0.3 |
| 51.498913 | -0.120850 | 0.7 |
| 51.496078 | -0.108919 | 0.7 |
| 51.496506 | -0.095873 | 0.7 |
| 51.503399 | -0.090723 | 0.7 |
| 51.508049 | -0.100336 | 0.7 |
| 51.508797 | -0.112610 | 0.7 |
| 51.505535 | -0.125227 | 0.7 |
| 51.502331 | -0.108061 | 0.7 |
+-----------+-----------+-----+

当前的SQL使用:

SELECT ppl.latitude,
       ppl.longitude,
       ppl.radius
FROM 
(
    people ppl
),
(
    SELECT latitude, longitude 
    FROM radiuses
) AS radius
WHERE (POW((ppl.longitude - radius.longitude) * 111.12 * COS(ppl.latitude), 2) + POW((ppl.longitude - radius.longitude) * 111.12, 2)) <= 4
GROUP BY ppl.id

MySQL的数据,你可以用它来测试您的查询,

INSERT INTO radiuses (id, latitude, longitude, km) VALUES ('1', '51.502117', '-0.103340', '0.3'), ('2', '51.498913', '-0.120850', '0.7'), ('3', '51.496078', '-0.108919', '0.7'), ('4', '51.496506', '-0.095873', '0.7'), ('5', '51.503399', '-0.090723', '0.7'), ('6', '51.508049', '-0.100336', '0.7'), ('7', '51.508797', '-0.112610', '0.7'), ('8', '51.505535', '-0.125227', '0.7'), ('9', '51.502331', '-0.108061', '0.7');

INSERT INTO people (id, latitude, longitude, radius) VALUES ('1', '51.517395', '-0.053129', '5.6'), ('2', '51.506607', '-0.116129', '0.7');

老摘要

注意:所有的经度和纬度都只是随机发。

我有一个小应用程序映射,用户可以将自己的一个纬度/经度位置的半径 ,用一公里半径。

现在,有一个可以把他的半径 ,在任何位置在地图上,每1公里半径(同一用户)其他用户。

类似这样的用户A是红色和用户B是蓝色的。

基本上, 用户A保存他的,看起来像这样的表半径:

+-----------+---------+-----------+-----------+
| radius_id | user_id | latitude  | longitude |
+-----------+---------+-----------+-----------+
|         1 |       1 | 81.802117 | -1.110035 |
|         2 |       1 | 81.798272 | -1.144196 |
|         3 |       1 | 81.726782 | -1.135919 |
+-----------+---------+-----------+-----------+

用户B存储他的另一个表看起来像这样半径- (注:他们只能存储每个账户1个坐标):

+---------+-----------+-----------+
| user_id | latitude  | longitude |
+---------+-----------+-----------+
|       6 | 81.444126 | -1.244910 |
+---------+-----------+-----------+

我希望能够拿起那些落入所定义的半径范围内的用户,即使半径的圆是感人,在地图画面。 只有标记C将能够拿起单个半径,当AB没有。

我敢肯定,这是可能的,但我不知道该怎么想出这种系统在MySQL。

我发现这对谷歌开发者网站上已经很接近了,但不只是它所执行我所需要的。

  • 创建与PHP,MySQL和谷歌地图商店定位器

编辑 :我已经找到一个更好的,这是非常接近,但仍然不是我要找的,因为它使用了1约束纬度,当我有一个表中的多个经度坐标。

  • 外接圆内由纬度/经度数据库中选择点

Answer 1:

几何图形的最重要的一点是,两个圆重叠的,如果他们的中心之间的距离小于其半径的总和。 因为我们正在做一个比较,我们可以使用距离的平方,因为这避免了平方根运算。 在原始的,每个半径固定为1,两个半径的总和为2,并且和的平方是4。

还有原来的问题和新问题之间有很大的区别。 在固定半径和第二的第一你有圈子,那么你有改变的半径的圆。 恒定4在比较表达[...distance^2...] <= 4需要被更换,因为这是在原有的固定半径的假象。 要实现这一点,添加km场到查询。 正如你应该检查一下,你没有使用ppl.radius在WHERE过滤器,所以这并不奇怪,改变该值没有改变您的查询结果。

SELECT ppl.latitude, ppl.longitude, ppl.radius
FROM 
  ( people ppl ),
  ( SELECT latitude, longitude, km FROM radiuses ) AS B
WHERE [...distance^2...] <= POW( ppl.radius + B.km, 2)

我应该说,这个问题花了更长的时间来了解比它应该有,因为你调用实体that's - 不一个人一个“半径”,当你真的有一个属​​性,它应该被称为'在两个不同的实体半径。 因此,名称等实体的东西描述。



Answer 2:

为了解决这个你需要理解圆的方程,它是这样对于任何点(x,y)的下降圈子内的中心(X1,Y1)和半径r单位

(x-x1)^2 + (y - y1)^2 <= r^2

where a^b = a to the power b

你的情况用户B的(纬度,经度)这里是圆的中心,用户A的(纬度,经度)是点(X,Y)和半径= 2千米。

但根本的问题是改变度的纬度经度来的,所以这里是解决方案,1度=111.12公里。 因此,要保持相同的单位在等式的两边,我们将其转换成公里

因此,我们的最终公式变为:

((x-x1)*111.12)^2 + ((y-y1)*111.12)^2 = 4      (=2^2) 

对于相同的SQL语句应该是这个样子

SELECT A.user_id, A.radius_id, A.latitude, A.logitude
FROM UserA AS A, 
     (SELECT user_id, latitude, longitude 
       FROM UserB 
       WHERE user_id = 8) AS B
WHERE (POW((A.latitude-B.latitude)*111.12, 2) + POW((A.longitude - B.longitude)*111.12, 2)) <= 4
/* **Edit** Here I have used (A.longitude - B.longitude)*111.12, for more accurate results one can replace it with (A.longitude - B.longitude)*111.12*cos(A.latitude)) or (A.longitude - B.longitude)*111.12*cos(B.latitude)) 

And, as i have suggested in the comments that first filter some records based on approximation, so whether one uses A.latitude or B.latitude it will not make much difference */

希望这将有助于...



Answer 3:

在你的问题的心脏是这个问题:“我怎么知道,如果两个圆重叠”。 这个问题的答案是:“如果他们的中心之间的距离小于其半径的总和”。 所以,你要寻找的是如何确定的两点之间的距离。

因为如果他们包括笛卡尔平面对方的回答是治疗的经度和纬度。 他们不(经度趋向于零,你从赤道靠近杆)。 现在,作为一个近似,它可能工作得很好,您的解决方案,这取决于您的解决方案所需的精度。 在另一方面,如果你需要这是非常准确的,你需要的haversine公式。 还有如何实现它在MySQL这里一个伟大的介绍:

http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL

从该演示文稿的幻灯片7,你有下面的公式:

3956*2*ASIN(SQRT(POWER(SIN((orig.lat-dest.lat)*pi()/180/2),2)+
    COS(orig.lat*pi()/180)*COS(dest.lat*pi()/180)*
    POWER(SIN((orig.lon-dest.lon)*pi()/180/2),2)))

注意,第一个数字是英里的地球平均半径; 改变,要为6371公里。

你如何使用这个计算出的距离将取决于不包括在您的文章的细节,比如你正在处理点的数量,地域分散,任何的性能要求,以及是否该数据是静态的或正在持续更新。

我提到这些事情,因为性能将是一个问题,特别是如果你有任何数据显著量和/或它的不断更新(如基于其手机的GPS数据用户的位置)。

您可以使用性能问题帮助的方法之一是使用方形而不是圆形,并使用一个度=111.12公里的逼近。 这样,你可以自动剔除掉那些明显远离彼此的任何点。 那么你只剩计算haversine公式只针对落在感兴趣的区域内的点的屈指可数。

我希望这是在指点你在正确的方向有帮助。



文章来源: Get results that fall within marker radiuses from database