2017-08-24 38 views
1

目前正在使用:如何基於距離特定緯度/經度來查詢Amazon Redshift表中的用戶IDS列表?

SELECT 
uid,lat,long, 
(
    6371 * 
    acos(
     cos(radians(value)) * 
     cos(radians(lat)) * 
     cos(
      radians(long) - radians(value) 
     ) + 
     sin(radians(value)) * 
     sin(radians(lat)) 
    ) 
) as distance 
FROM 
    table name 
WHERE 
    lat IS NOT Null AND long IS NOT Null 
HAVING 
    distance < 25 
ORDER BY 
    distance 
LIMIT 
    25; 
+0

@Serg美麗的編輯,我從來沒有見過半正矢/大圓不看起來很醜。 –

+0

@TimBiegeleisen應歸於OP。我剛加了一個ident,ctl/K。 Upvoting爲美麗的acos。 – Serg

+0

@TimBiegeleisen我喜歡爲此使用UDF! https://stackoverflow.com/questions/30259410/query-to-calculate-sum-of-distance-longitude-latitude-in-consecutive-rows-in – Strawberry

回答

1

MySQL的排序超載HAVING條款,以允許它被用作與可用的別名一個WHERE條款。雖然紅移沒有這個功能,你可以先計算在CTE或子查詢的距離,然後用計算的距離場,避免WHERE子句中重複距離計算:

WITH cte AS (
    SELECT 
     uid, 
     lat, 
     long, 
     (
      6371 * 
      acos(
       cos(radians(value)) * 
       cos(radians(lat)) * 
       cos(
        radians(long) - radians(value) 
       ) + 
       sin(radians(value)) * 
       sin(radians(lat)) 
      ) 
     ) AS distance 
    FROM yourTable 
    WHERE 
     lat IS NOT Null AND 
     long IS NOT Null 
) 

SELECT  
    t.uid, 
    t.lat, 
    t.long 
FROM cte t 
WHERE t.distance < 25 
ORDER BY t.distance 
LIMIT 25; 

如果你的版本Redshift不支持CTE,或者您不想使用CTE,只需將上述CTE放入子查詢中即可。

+0

這似乎在緯度上返回重複值並且不同用戶標識符的經度列以及距離,檢查數據庫中是否存在具有相同經度/長度的不同用戶標識符的問題。 –

+0

@NeilNandi然後這是一個不同於你在你的問題中提出的問題。我已經直接回答你的原始問題。 –

+0

是的。感謝您的解決方案。似乎工作正常@蒂姆 –

0

我創建了一個UDF我自己:

CREATE OR REPLACE FUNCTION public.f_distance(lat1 double precision, lon1 double precision, lat2 double precision, lon2 double precision) 
RETURNS double precision 
IMMUTABLE AS $$ 
    import math 
    if lat1==None or lat2==None or lon1==None or lon2==None: 
     return None 
    if lat1==lat2 and lon1==lon2: 
     return 0 
    else: 
     return (6371*math.acos(
       math.cos(math.radians(lat1))*math.cos(math.radians(lat2))*math.cos(math.radians(lon2)-math.radians(lon1))+ 
       math.sin(math.radians(lat1))*math.sin(math.radians(lat2)) 
      ) 
     ) 
$$ LANGUAGE plpythonu; 

所以它可以直接使用這樣的:

SELECT uid,lat,long,f_distance(search_lat,search_long,lat,long) as distance 
FROM your_table 
WHERE f_distance(search_lat,search_long,lat,long)<25 
ORDER BY 4 
LIMIT 25 
相關問題