2013-06-11 3 views
4

다음 SQL (SQL Server)을 가지고 있고 대부분 작동합니다. 문제는 내가 진실이 아닌 광장을 만들고 있다는 것입니다. 내 목표는 위도와 경도가있는 도시와 주를 통과 한 다음 그 위도의 100 마일 반경 내에있는 모든 도시를 찾아내는 것입니다. 위도와 경도는 DB에 저장되므로 모든 값이 있습니다. 나는 그것을하는 더 정확한 방법이 필요하다. 여기에 지금까지 내 코드입니다 :주어진 반지름으로 결과 집합을 반환하는 방법

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

을 나는 [피타고라스 공식]을 제안하고 있었다 (http://stackoverflow.com/a/13032393/87698) ('된 우편 번호 SELECT * FROM WHERE ((위도 - @istartlat) * (경도 - @istartlong) + (경도 - @istartlong) <= (@Radius * @Radius)'), 그러나 나는 이것이 변환으로 인해 더 복잡하다는 것을 깨달았습니다. 위도/경도로 마일. – Heinzi

+0

아마도 sql에서 사각형을 도시로 반환 한 다음 응용 프로그램 측에서 필터링하여 정밀도를 추가하십시오. sql이 많은 수의 클라이언트에 대해 너무 많은 수의 처리를 수행하는 것은 좋지 않습니다. 더 많은 앱 서버를 추가하는 것은 저렴합니다. –

+0

도시 간 거리가 자주 변경되지 않으므로 이러한 결과를 모두 캐시 해 두십시오. –

답변

2

저는 과거에 큰 원형 거리를 사용했습니다.

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((@[email protected])/2.0E)) + 
    (cos(@lat1) * cos(@lat2) * square(sin((@[email protected])/2.0E)))) 

set @distance = 
    @radius * (2.0E *asin(case when 1.0E < @a then 1.0E else @a end)) 

return @distance 

end 
2

확실하지 않음이 도움이된다면,하지만 여기에 오류가 있다고 생각 :

SELECT @LatRange = @Radius/((6076/5280) * 60) 

은 (/ 5280 6076) 부분은 항상 1

로 평가합니다은
+1

이 상수가 항상 같으면 그냥 69.04545로 바꾸십시오. –

0

이 기능은 인 박스 SQL 서버 2012 이상 할 수 있습니다 : 구현은 아래 당신이 무엇에 관해 얘기하는지 어떻게 사용될 수있는 서로 다른 두 점 사이의 거리를 알려줍니다. Query Spatial Data for Nearest Neighbor 참조 :

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); 
관련 문제