假设我有一个城市的纬度和经度,我需要找出该位置 100 英里范围内的所有机场。我将如何做到这一点?我的数据驻留在 SQL Server 中。一张表包含所有城市信息,包括纬度和经度,另一张表包含机场信息,经度和纬度。
问问题
2369 次
2 回答
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
于 2013-04-23T18:48:50.837 回答
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 zipcode=@ZIP
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)
于 2013-04-23T18:30:01.350 回答