2013-04-23 132 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