给定一个包含4个圆圈的数据库,其中每个圆圈都有一个半径和一个地理位置中心:
id | radius | latitude | longitude
---+--------+----------+----------
1 | 3 | 40.71 | 100.23
2 | 10 | 50.13 | 100.23
3 | 12 | 39.92 | 100.23
4 | 4 | 80.99 | 100.23
注意:每个圆圈的经度都是相同的,以保持简单。
假设我们在圈子2上,我想根据latitude
/ longitude
坐标和每个圈子的radius
找到附近的每个圆圈。
例如,根据纬度/经度坐标,我们有这个顺序:
9.42 <- 50.13 - 40.71
)10.21 <- 50.13 - 39.92
)30.86 <- 80.99 - 50.13
)但是根据纬度/经度坐标和每个圆的半径,我们应该有:
1.79 <- 12 - 10.21
)6.42 <- 9.42 - 3
)26.86 <- 30.86 - 4
)在SQL中有一种简单的方法吗?
答案 0 :(得分:1)
postgresql的contrib中提供的cube
和earthdistance
扩展可以处理这样做,以产生至少近似的答案。具体来说,他们认为地球是一个简单的球体,这使得数学变得更容易。
使用这些扩展程序,您可以生成圆圈2和其他圆圈之间的距离,如下所示:
select circle.id,
earth_distance(ll_to_earth(circle.latitude, circle.longitude),
ll_to_earth(x.latitude, x.longitude))
from circle,
circle x
where x.id = 2 and circle.id <> x.id
order by 2;
校正圆半径应该只涉及从上方距离减去x.radius
和circle.radius
,尽管您需要考虑半径所在的单位。默认情况下,earth_distance
将以米为单位计算一个值。
现在,让查询执行除扫描整个圆圈列表以及计算每个圆圈的距离以外的其他内容,然后对它们进行排序和限制,这更具挑战性。有几种方法:
第二个选项基本上以:
开头create table circle_distance as
select a.id as a_id, b.id as b_id,
earth_distance(ll_to_earth(a.latitude, a.longitude),
ll_to_earth(b.latitude, b.longitude))
from circle a, circle b
where a.id <> b.id;
alter table circle_distance add unique(a_id, b_id);
create index on circle_distance(a_id, earth_distance);
然后一些相当繁琐的函数来删除/插入circle_distance
中的相关行,由circle
上的触发器调用。这意味着您可以:
select b_id from earth_distance where a_id = $circle_id order by earth_distance limit $n
此查询将能够使用(a_id,earth_distance)
上的索引进行快速扫描。
答案 1 :(得分:0)
我建议查看PostGIS地理数据类型及其相关功能(例如:ST_Distance
),而不是重新发明轮子
答案 2 :(得分:0)
我会告诉你以下内容:
创建1个表来计算相对于起始圆的相对距离
例如:
id | calc1 | calc2
---+--------+----------
1 | 9.42 | 1.97
3 | 10.21 | 6.42
4 | 30.86 | 62.86
Calc1是没有半径的计算 calc2是半径
的计算然后创建一个存储过程,首先在运行时删除表,然后用正确的数据填充它,然后只读取目标表中的结果
Intrudoction to store procedures You will allso need cursor for this
答案 3 :(得分:0)