2013-04-23 120 views
1

說我有一個城市的經緯度,我需要找出距離這個地點100英里範圍內的所有機場。我怎麼做到這一點?我的數據駐留在SQL Server中。 1張桌子有拉特和長的所有城市信息,另一張桌子有拉特和長的機場信息。SQL Server:計算Lat/Long的半徑?

+0

您使用的是空間數據嗎? – swasheck 2013-04-23 18:22:12

+0

不,他們只是存儲爲小數點 – Matt 2013-04-23 18:23:46

+0

哪個版本的sql server? – swasheck 2013-04-23 18:29:05

回答

3

我在幾年前使用過/寫過,並且它足夠接近我所需要的。如果我沒有記錯的話,公式的一部分會考慮地球曲率,但它已經有一段時間了。我使用郵政編碼,但您可以輕鬆地適應城市 - 相同的邏輯。

ALTER PROCEDURE [dbo].[sp_StoresByZipArea] (@zip nvarchar(5), @Radius float) AS 

DECLARE @LatRange float 
DECLARE @LongRange float 
DECLARE @LowLatitude float 
DECLARE @HighLatitude float 
DECLARE @LowLongitude float 
DECLARE @HighLongitude float 

DECLARE @istartlat float 
DECLARE @istartlong float 

SELECT @iStartlat=Latitude, @iStartLong=Longitude from zipcodes where [email protected] 

SELECT @LatRange = @Radius/((6076/5280) * 60) 
SELECT @LongRange = @Radius/(((cos((@iStartLat * 3.141592653589/180)) * 6076.)/5280.) * 60) 

SELECT @LowLatitude = @istartlat - @LatRange 
SELECT @HighLatitude = @istartlat + @LatRange 
SELECT @LowLongitude = @istartlong - @LongRange 
SELECT @HighLongitude = @istartlong + @LongRange 

/** Now you can create a SQL statement which limits the recordset of cities in this manner: **/ 

SELECT * FROM ZipCodes 
WHERE (Latitude <= @HighLatitude) AND (Latitude >= @LowLatitude) AND (Longitude >= @LowLongitude) AND (Longitude <= @HighLongitude) 
+0

如果我想要一個100英里的半徑,數學會有什麼不同? – Matt 2013-04-24 15:22:02

+1

否,半徑作爲參數傳遞到SP中。 – 2013-04-24 15:30:56

+0

謝謝你,這真棒! – Matt 2013-04-24 16:00:13

4

首先...轉換城市的數據點

DECLARE @point geography; 

SELECT geography::STPointFromText('POINT(' + CAST(@lat AS VARCHAR(20)) + ' ' + 
        CAST(@lon AS VARCHAR(20)) + ')', 4326) 

其中@lat和@lon是城市問題的經度和緯度。

然後你就可以查詢該表...

SELECT [column1],[column2],[etc] 
FROM [table] 
WHERE @point.STBuffer(160934.4).STIntersects(geography::STPointFromText(
    'POINT(' + CAST([lat] AS VARCHAR(20)) + ' ' + 
    CAST([lon] AS VARCHAR(20)) + ')', 4326)); 

,其中160934.4是米100英里數。

雖然這會很慢。如果你想做更多的空間工作,你可以添加一個持續的計算列(因爲經緯度點不會真的改變),然後使用空間索引。

ALTER TABLE [table] 
    ADD geo_point AS geography::STPointFromText('POINT(' + CAST([lat] AS VARCHAR(20)) 
    + ' ' + CAST([lon] AS VARCHAR(20)) + ')', 4326) PERSISTED; 

CREATE SPATIAL INDEX spix_table_geopt 
    ON table(geo_point) 
    WITH (BOUNDING_BOX = (0, 0, 500, 200)); --you'd have to know your data 
+0

其他答案也很好。我添加了這個作爲替代方法來解決這個問題,特別是在SQL Server 2008中,特別是如果你要做大量的空間工作。 – swasheck 2013-04-23 18:57:39