2015-09-06 12 views
1

我有一個SQL數據庫集,我分配了座標(lat,long)。我想問一下距離我內點5公里範圍內的點。我想知道如何以不收集不必要記錄的方式構建查詢?SQL查找屬於一個圓的座標

+1

什麼數據庫引擎和版本?你試過什麼了? – duffn

+0

我使用基於Boot Spring/Hibernate的MySQL數據庫。我不知道是否需要下載所有記錄,然後計算它們與中心點的距離,如果我可以立即撤消查詢。 – lukassz

+0

你需要什麼精度?你能否假設經緯度爲0.05英里,長度約爲5公里? – Balinti

回答

1

既然你正在談論的大約5公里的距離很小,我們可能不會在南極或北極,我們可以用經度和緯度值的近似電網系統工作的直接附近。 latidude中的每個學位相當於km_per_lat=6371km*2*pi/360degrees = 111.195km的距離。兩個縱向線是1度之間的距離間隔取決於實際緯度:

km_per_long=km_per_lat * cos(lat) 

對於這裏在北德國區域(51度北)這個值將是周圍69.98公里。

因此,假設我們感興趣的是小的距離圍繞lat0和long0我們可以有把握地認爲翻譯因素縱向和橫向的角度將保持不變,我們可以簡單地套用公式

SELECT 111.195*sqrt(power([email protected],2) 
        +power(cos(pi()/180*@lat0)*([email protected]),2)) dist_in_km FROM tbl 

既然你要使用的公式您選擇的WHERE子句中,你可以使用以下命令:

SELECT * FROM tbl 
WHERE 111.195*sqrt(power([email protected],2) 
        +power(cos(pi()/180*@lat0)*([email protected]),2)) < 5 

select語句將在度給出的緯度和經度值的工作(在十進制表示)。因此,我們必須將cos()函數內的值乘以pi()/180來將其轉換爲弧度。

如果你有較大的距離(>500公里)工作那麼它可能是更好的應用在導航中使用的適當的距離式等

cos(delta)=cos(lat0)*cos(lat)*cos(long-long0) + sin(lat0)*sin(lat) 

通過施加acos()你只需乘法計算實際角度增量後由地球半徑R = 6371km = 180/pi()*111.195km該值,你有你想要的距離(在這裏看到:Wiki: great circle distance

更新(回覆評論):

不知道你打算做什麼。如果只有一個要比較反對然後參考位置,你當然可以預編譯距離計算有點像

SELECT @lat0:=51,@long0:=-9; -- assuming a base position of: 51°N 9°E 
SELECT @rad:=PI()/180,@fx:[email protected]*6371,@fy:[email protected]*cos(@rad*@lat0); 

你的距離計算隨後將簡化到只是

SELECT @dist:=sqrt(power(@fx*([email protected]),2)+power(@fy*([email protected]),2)) 

與當前在latlong的位置(不需要餘弦函數)。無論您是希望首先將所有傳入位置存儲在數據庫中,還是希望在Spring,Java或您正在使用的任何語言以外的地方執行計算,都取決於您。等式在那裏,易於使用。

+0

我想在使用Hibernate的Boot Spring應用程序中使用它。它是否支付直接在數據庫中計算距離?從數據庫中獲取所有記錄然後選擇它們會更好嗎? – lukassz

-1

我會去與Euklid。 dist=sqrt(power(x1-x2,2)+power(y1-y2,2))。它工作到處。也許你必須添加一個轉換到x/y座標,如果度數不能很容易地轉換成km。

比你可以去選擇你喜歡的一切WHERE x IS BETWEEN (x-5) AND (x+5) AND y IS BETWEEN (y-5) AND (y+5)。現在你可以用Euklid檢查結果。

有了結果順序的優化,你可以先取得更好的成績。也許有一種方法可以將Euklid帶到SQL中。

+0

笛卡爾距離不適用於經緯度距離計算,除了非常接近彼此和赤道的位置。 –

+0

嗯,在我看來,5公里非常接近。而且,正如我所說的,可能需要進行轉換,其中cars10闡述得非常好;-) – queuverflow