Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何返回具有给定半径的结果集_Sql_Sql Server - Fatal编程技术网

Sql 如何返回具有给定半径的结果集

Sql 如何返回具有给定半径的结果集,sql,sql-server,Sql,Sql Server,我有下面的SQL Server,它在大多数情况下都能工作。问题是我真的在创造一个正方形,而不是一个真正的圆。我的目标是通过一个有拉特和拉特的城市和州,然后找到拉特半径100英里范围内的所有城市。纬度和经度存储在数据库中,因此我的所有值都在那里。我只是需要一个更精确的方法。以下是我迄今为止的代码: ALTER PROCEDURE [dbo].[sp_StoresByZipArea] (@zip nvarchar(5), @Radius float) AS DECLARE @LatRange f

我有下面的SQL Server,它在大多数情况下都能工作。问题是我真的在创造一个正方形,而不是一个真正的圆。我的目标是通过一个有拉特和拉特的城市和州,然后找到拉特半径100英里范围内的所有城市。纬度和经度存储在数据库中,因此我的所有值都在那里。我只是需要一个更精确的方法。以下是我迄今为止的代码:

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);