在Netezza中,我习惯使用INZA包和ST_Distance函数。 Redshift中是否有人知道类似的方式?我用它进行了大量的计算和连接。
答案 0 :(得分:7)
检查一下!!
------- DISTANCE FUNCTION ---------
CREATE FUNCTION DISTANCE (orig_lat float, orig_long float, dest_lat float, dest_long float)
RETURNS float
STABLE
AS $$
import math
r = 3963.1676
phi_orig = math.radians(orig_lat)
phi_dest = math.radians(dest_lat)
delta_lat = math.radians(dest_lat - orig_lat)
delta_long = math.radians(dest_long - orig_long)
a = math.sin(delta_lat/2) * math.sin(delta_lat/2) + math.cos(phi_orig) \
* math.cos(phi_dest) * math.sin(delta_long/2) * math.sin(delta_long/2)
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
d = r * c
return d
$$ LANGUAGE plpythonu
;
答案 1 :(得分:1)
alexanderlz建议的postgres_fdw模块不能与Redshift一起使用,因为最低要求是Postgres 8.1(只读)。 Redshift目前使用Postgres 8.0.2。您可以使用dblink来获得类似的功能。
答案 2 :(得分:0)
您必须计算外部 redshift,
您可以尝试以下方法:
由于redshift实现了postgres界面,你可以利用postgres FDW的能力,并将它们统一到一个postgres数据源,你可以在一个查询中进行连接。
即。 :postgres的实例(称之为“master”),安装了postgis,通过 fdw 连接到redshift。这样,您就可以对红移数据使用地理定位查询。
答案 3 :(得分:0)
虽然python udf方法没有任何问题,但我们发现python udf比本地sql udf花费的时间更长,消耗的资源也更多(并且我们运行了数十亿条记录)。这就是我们使用的方法,并且肯定不是完美的方法(即,我们将地球半径平均为3961英里,但我们不需要精确使用)。
CREATE OR REPLACE FUNCTION public.f_haversine (
float, -- $1: latitude_1
float, -- $2: longitude_1
float, -- $3: latitude_2
float -- $4: longitude_2
)
RETURNS FLOAT
IMMUTABLE
AS $$
SELECT 2 * 3961 * ASIN(SQRT( POWER((SIN(RADIANS(($3 - $1) / 2))) , 2) + COS(RADIANS($1)) * COS(RADIANS($3)) * POWER((SIN(RADIANS(($4 - $2) / 2))) , 2) ))
$$ LANGUAGE sql;
这只是使用内置的sql数学功能手动计算的Haversine距离。这将返回以英里为单位的距离,如果要以另一度量单位返回距离,则可以将3961
替换为您想要的任何单位的地球平均半径(即6371
公里,或者6371000
代表米等)