Sql 如何返回具有给定半径的结果集
我有下面的SQL Server,它在大多数情况下都能工作。问题是我真的在创造一个正方形,而不是一个真正的圆。我的目标是通过一个有拉特和拉特的城市和州,然后找到拉特半径100英里范围内的所有城市。纬度和经度存储在数据库中,因此我的所有值都在那里。我只是需要一个更精确的方法。以下是我迄今为止的代码:Sql 如何返回具有给定半径的结果集,sql,sql-server,Sql,Sql Server,我有下面的SQL Server,它在大多数情况下都能工作。问题是我真的在创造一个正方形,而不是一个真正的圆。我的目标是通过一个有拉特和拉特的城市和州,然后找到拉特半径100英里范围内的所有城市。纬度和经度存储在数据库中,因此我的所有值都在那里。我只是需要一个更精确的方法。以下是我迄今为止的代码: ALTER PROCEDURE [dbo].[sp_StoresByZipArea] (@zip nvarchar(5), @Radius float) AS DECLARE @LatRange f
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)
不确定这是否有帮助,但我认为这里有一个错误:
SELECT @LatRange = @Radius / ((6076 / 5280) * 60)
6076/5280零件的计算值始终为1。我过去曾使用大圆距离来进行此操作。下面的实现告诉您两个不同点之间的距离,这可以用来做您所说的事情:
create function dbo.GreatCircleDistance
(
@Latitude1 float,
@Longitude1 float,
@Latitude2 float,
@Longitude2 float
)
returns float
as
/*
FUNCTION: dbo.GreatCircleDistance
Computes the Great Circle distance in kilometers
between two points on the Earth using the
Haversine formula distance calculation.
Input Parameters:
@Longitude1 - Longitude in degrees of point 1
@Latitude1 - Latitude in degrees of point 1
@Longitude2 - Longitude in degrees of point 2
@Latitude2 - Latitude in degrees of point 2
*/
begin
declare @radius float
declare @lon1 float
declare @lon2 float
declare @lat1 float
declare @lat2 float
declare @a float
declare @distance float
-- Sets average radius of Earth in Kilometers
set @radius = 6371.0E
-- Convert degrees to radians
set @lon1 = radians( @Longitude1 )
set @lon2 = radians( @Longitude2 )
set @lat1 = radians( @Latitude1 )
set @lat2 = radians( @Latitude2 )
set @a = sqrt(square(sin((@lat2-@lat1)/2.0E)) +
(cos(@lat1) * cos(@lat2) * square(sin((@lon2-@lon1)/2.0E))) )
set @distance =
@radius * ( 2.0E *asin(case when 1.0E < @a then 1.0E else @a end ))
return @distance
end
此功能在SQL Server 2012及更高版本的box中提供。见:
我想建议使用SELECT*FROM ZipCodes,其中纬度-@istartlat*纬度-@istartlat+经度-@istartlong*经度-@istartlong可能有sql返回广场中的城市,然后通过在应用程序端进行过滤来增加精度。让sql做这么多的数字运算可能不好,尤其是对于大量的客户机。添加更多的应用服务器是很便宜的。城市之间的距离不会经常改变,所以请随意缓存所有这些结果!如果该常数始终不变,则用69.04545替换
DECLARE @g geography;
DECLARE @h geography;
-- SRID 4326 specifies the use of WGS 84 coordinate system (same as GPS)
SET @g = geography::STGeomFromText('POINT(-122.360 47.656)', 4326);
SET @h = geography::STGeomFromText('POINT(-122.34900 47.65100)', 4326);
-- Returns 995 meters
SELECT @g.STDistance(@h);