Sql 如何使用Postgres扩展在半径范围内搜索?
求地球表面的距离意味着使用大圆距离,用哈弗森公式计算,也被称为球面余弦定律公式 问题是:给定一张带有纬度和经度的位置表,其中哪些位置距离给定位置最近 我有以下疑问:Sql 如何使用Postgres扩展在半径范围内搜索?,sql,postgresql,Sql,Postgresql,求地球表面的距离意味着使用大圆距离,用哈弗森公式计算,也被称为球面余弦定律公式 问题是:给定一张带有纬度和经度的位置表,其中哪些位置距离给定位置最近 我有以下疑问: SELECT z.id, z.latitude, z.longitude, p.radius, p.distance_unit * DEGREES(ACOS(COS(RADIANS(p.latpoint))
SELECT z.id,
z.latitude, z.longitude,
p.radius,
p.distance_unit
* DEGREES(ACOS(COS(RADIANS(p.latpoint))
* COS(RADIANS(z.latitude))
* COS(RADIANS(p.longpoint - z.longitude))
+ SIN(RADIANS(p.latpoint))
* SIN(RADIANS(z.latitude)))) AS distance
FROM doorbots as z
JOIN ( /* these are the query parameters */
SELECT 34.0480698 AS latpoint, -118.3589196 AS longpoint,
2 AS radius, 111.045 AS distance_unit
) AS p ON 1=1
WHERE z.latitude between ... and
z.longitude between ...
如何使用扩展来更改查询中的复杂公式
这是否等同于改变
SELECT z.id,
z.latitude, z.longitude,
p.radius,
round(earth_distance(ll_to_earth(p.latpoint, p.longpoint), ll_to_earth(z.latitude, z.longitude))::NUMERIC,0) AS distance
FROM doorbots as z
JOIN ( /* these are the query parameters */
SELECT 34.0480698 AS latpoint, -118.3589196 AS longpoint,
2 AS radius, 111.045 AS distance_unit
) AS p ON 1=1
WHERE z.latitude between ... and
z.longitude between ...
通过以下查询,您可以充分利用earthdistance: 位置足够近,即在1000000.0米范围内-621.371192英里至34.0480698,-118.3589196: 使用索引:足够近的位置,即在1000000.0米-621.371192英里到34.0480698,-118.3589196之间: 使用索引:最接近34.0480698,-118.3589196的前5个位置:
通过以下查询,您可以充分利用earthdistance: 位置足够近,即在1000000.0米范围内-621.371192英里至34.0480698,-118.3589196: 使用索引:足够近的位置,即在1000000.0米-621.371192英里到34.0480698,-118.3589196之间: 使用索引:最接近34.0480698,-118.3589196的前5个位置:
地球到地球的距离地球到地球的纬度,经度,地球到地球的距离$1,$2<$3或点z.经度,纬度点$2,$1<$3-关于地球距离的文档对我来说似乎很明显。你到底不明白什么也许你想加入一些索引?对于你的更新:是的,这似乎是一个相当的变化,但是z.latitude之间。。。和z之间的经度。。。不在半径范围内搜索;相反,在一个矩形中,它实际上也不是一个矩形:它是一个球形表面上的一个矩形区域。地球到地球的距离。纬度,经度,地球到地球的距离$1,$2<$3或点z.经度,z.纬度点$2,$1<$3。关于地球距离的文档对我来说似乎很明显。你到底不明白什么也许你想加入一些索引?对于你的更新:是的,这似乎是一个相当的变化,但是z.latitude之间。。。和z之间的经度。。。不在半径范围内搜索;实际上,在矩形中,它也不是矩形:它是球形表面上的矩形区域。
select *
from doorbots z
where earth_distance(ll_to_earth(z.latitude, z.longitude), ll_to_earth(34.0480698, -118.3589196)) < 1000000.0; -- in meters
select *
from doorbots z
where point(z.longitude, z.latitude) <@> point(-118.3589196, 34.0480698) < 621.371192; -- in miles
select *
from doorbots z
order by earth_distance(ll_to_earth(z.latitude, z.longitude), ll_to_earth(34.0480698, -118.3589196))
limit 5;
select *
from doorbots z
order by point(z.longitude, z.latitude) <@> point(-118.3589196, 34.0480698)
limit 5;
create index idx_doorbots_latlong
on doorbots using gist (earth_box(ll_to_earth(latitude, longitude), 0));
with p as (
select 34.0480698 as latitude,
-118.3589196 as longitude,
1000000.0 as max_distance_in_meters
)
select z.*
from p, doorbots z
where earth_box(ll_to_earth(z.latitude, z.longitude), 0) <@ earth_box(ll_to_earth(p.latitude, p.longitude), p.max_distance_in_meters)
and earth_distance(ll_to_earth(z.latitude, z.longitude), ll_to_earth(p.latitude, p.longitude)) < p.max_distance_in_meters;
select z.*
from doorbots z
order by earth_box(ll_to_earth(z.latitude, z.longitude), 0) <-> earth_box(ll_to_earth(34.0480698, -118.3589196), 0)
limit 5;