获取属于数据库标记半径的结果

Mac*_*Mac 20 mysql math markers

2012年11月16日更新

我想再次提出这个问题,提供一个新的奖励,以获得可靠,良好的解决方案.似乎只有解决方案(shubhansh的答案)现在才能有效地运作.我会解释原因.

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

在此输入图像描述

正如你所看到的,two这张地图中有人有eight半径,基本上我只得到那个人Person A,但我没有得到Person B,我猜测SQL没有正确地把它拿起来我需要它准确从人的半径和标记半径精确.

看起来拾取的是在半径内部,而不是那些与半径重叠的那些,我需要它能够为任何相互重叠的半径拾取任何结果.

我正在寻找一个精确而准确的SQL而不是shubhansh的答案.您可以在下面阅读以了解我是如何确切地需要查询来采取行动并选择准确的人员.

数据,PEOPLE:

+-----------+-----------+--------+
| latitude  | longitude | radius |
+-----------+-----------+--------+
| 51.517395 | -0.053129 | 5.6    |
| 51.506607 | -0.116129 | 0.7    |
+-----------+-----------+--------+
Run Code Online (Sandbox Code Playgroud)

请注意,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 |
+-----------+-----------+-----+
Run Code Online (Sandbox Code Playgroud)

我使用的当前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
Run Code Online (Sandbox Code Playgroud)

可用于测试查询的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');
Run Code Online (Sandbox Code Playgroud)

旧的总结

注意:所有纬度和经度都是随机产生的.

我有一个地图小程序,用户可以将其半径定位在1/3 的纬度/经度位置.

现在,还有另一个用户可以在地图上的任何位置放置半径,每个半径为1km半径(与上面的用户相同).

像这样用户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 |
+-----------+---------+-----------+-----------+
Run Code Online (Sandbox Code Playgroud)

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

+---------+-----------+-----------+
| user_id | latitude  | longitude |
+---------+-----------+-----------+
|       6 | 81.444126 | -1.244910 |
+---------+-----------+-----------+
Run Code Online (Sandbox Code Playgroud)

我希望能够在地图图片中拾取属于定义半径的用户,即使半径圆圈正在触摸.只有标记C才能获得单个半径,何时AB不可以.

我确信这是可能的,但我不知道如何在MySQL中提出这种系统.

我在谷歌开发者网站上发现了这一点,但它不仅仅是我所需要的.

编辑:我发现了一个更好的,这是非常接近的,但仍然不是我想要的,因为当我在表中有多个时它使用1个纬度和经度坐标的界限.

jsi*_*ist 14

为了解决这个问题,你需要了解圆的方程,这是这样的.对于任何点(x,y)落入圆中心(x1,y1)和半径r单位是

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

where a^b = a to the power b
Run Code Online (Sandbox Code Playgroud)

在您的情况下,用户B(纬度,经度)是圆的中心,用户A(纬度,经度)是点(x,y)和半径= 2kms.

但基本问题是纬度变化到经度,所以这里是解,1度= 111.12 km.因此,为了保持方程两边的单位相同,我们将其转换为Kms

所以我们的最终等式变为:

((x-x1)*111.12)^2 + ((y-y1)*111.12)^2 = 4      (=2^2) 
Run Code Online (Sandbox Code Playgroud)

同样的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 */
Run Code Online (Sandbox Code Playgroud)

希望这会有所帮助......

  • 仅在赤道一度= 111.12公里; 当你向极点移动时,纬度保持相对恒定但经度接近于零,所以这个解决方案将越来越不准确离你的赤道越来越远. (2认同)

Eth*_*own 7

问题的核心是"如何知道两个圆圈是否重叠"的问题.答案是"如果它们的中心之间的距离小于它们的半径之和".所以你要找的是如何确定两点之间的距离.

另一个答案是将纬度和经度视为包含笛卡尔平面.他们不这样做(当你从赤道接近极点时,经度往往趋于零).现在,作为近似值,它可能适用于您的解决方案,具体取决于您的解决方案所需的准确性.另一方面,如果您需要非常准确,则需要使用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)))
Run Code Online (Sandbox Code Playgroud)

请注意,第一个数字是以英里为单位的地球平均半径; 将其更改为6371公里.

您如何使用此计算距离将取决于您的帖子中未包含的详细信息,例如您要处理的点数,地理范围,任何性能要求以及数据是否为静态或是否持续更新.

我提到这些是因为性能会成为一个问题,特别是如果你有大量数据和/或它不断更新(比如用户根据手机GPS数据的位置).

可以帮助解决性能问题的一种方法是使用正方形而不是圆形,并使用一度= 111.12 km的近似值.这样你就可以自动剔除任何明显远离彼此的点.然后你只剩下计算Haversine公式只针对感兴趣区域内的少数几个点.

我希望这有助于指出你正确的方向.


eh9*_*eh9 6

几何的基本点是,如果两个圆的中心之间的距离小于它们的半径之和,则两个圆重叠.由于我们正在进行比较,我们可以使用距离的平方,因为这避免了平方根操作.在原始中,每个半径固定为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)
Run Code Online (Sandbox Code Playgroud)

我应该说这个问题需要花费更长的时间来理解它应该具有的,因为你把实体 - 这不是一个人称为"半径",当你真的有一个应该被称为'的财产时两个不同实体上的"半径".因此,将其他实体命名为描述性内容.