2013-04-30 2 views
1

Учитывая следующий SQL, который возвращает список аэропортов, основанных на данном городе, как бы я еще больше его улучшил, чтобы отсортировать результаты по ближайшим к мне? Похоже, он должен быть достаточно простым, но он ускользает от меня.SQL Server: поиск ближайшего местоположения

DECLARE @latRange float 
DECLARE @LongRange float 
DECLARE @LowLatitude float 
DECLARE @HighLatitude float 
DECLARE @LowLongitude float 
DECLARE @HighLongitude float 
DECLARE @Radius float = 100 


DECLARE @istartlat float 
DECLARE @istartlong float 

Select @istartlat=Latitude, @istartlong=Longitude from Lookup where PlaceName = '"Franklin"' and StateCode = '"AR"' 

Select @latRange = @Radius/((6076/5280) * 60) 
Select @LongRange = @Radius/(((COS((@istartlat * 3.14592653589/180)) * 6076.)/5280. * 60)) 

Select @LowLatitude = @istartlat - @latRange 
Select @HighLatitude = @istartlat + @latRange 
Select @LowLongitude = @istartlong - @LongRange 
Select @HighLongitude = @istartlong + @LongRange 

Select a.City, a.State, a.AirportCode, a.AirportName, a.CountryCode 
from PFM_Airport a 
where (a.Latitude <= @HighLatitude) and (a.Latitude >= @LowLatitude) and (a.Longitude >= @LowLongitude) 
and (a.Longitude <= @HighLongitude) 
--and a.CountryCode in ('USA', 'CANADA') 
order by a.Latitude, a.Longitude; 
+0

SQL имеет константу pi, ['PI()'] (http://msdn.microsoft.com/en-us/library/ms189512.aspx). Вам не нужно жестко указывать его, если вы не намеренно округлите его до определенного значения. – valverij

+3

Поддерживает ли ваша версия SQL Server геопространственные пространственные типы данных? – JOBG

+0

В настоящее время lat и long хранятся в виде поплавков – Matt

ответ

4

@hatchet правильно .. Предположим, что ваш экземпляр поддержки SQL Server geography spatial data то вам следует использовать этот тип данных для расчетов, вы можете также найти полезную часть этого кода, просто замените имена таблиц, условные операторы и разбиение на страницы по мере необходимости:

ALTER PROCEDURE [dbo].[SP_NearestPOIReloaded] 
(
    -- Add the parameters for the stored procedure here 
    @LAT float, 
    @LNG float, 
    @DISTANCE int, 
    @CURRENTPAGE Int, 
    @PAGESIZE Int, 
    @COUNT int OUTPUT 
    ) 
AS 
BEGIN 
    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    SET NOCOUNT ON; 

/*for pagination*/ 
SET @COUNT = (SELECT COUNT(*) FROM dbo.Lugares as [L] WHERE dbo.DistanceBetween(@LAT, @LNG, [L].lat, [L].lng) < @DISTANCE) 

/*paginated resultset*/ 
SELECT * FROM (
SELECT ROW_NUMBER()Over(Order by dbo.DistanceBetween(@LAT, @LNG, [L].lat, [L].lng) Asc) As [RowNum], dbo.DistanceBetween(@LAT, @LNG, [L].lat, [L].lng) as [distance], [L].*, [E].name as [empresaName], [U].userName as [userName] 
FROM dbo.Lugares as [L], dbo.Empresas as [E], dbo.Usuarios as [U] 
WHERE dbo.DistanceBetween(@LAT, @LNG, [L].lat, [L].lng) < @DISTANCE AND 
[L].usuarioId = [U].id AND [L].empresaId = [E].id 
) 
AS ResultadoPaginado 
WHERE RowNum BETWEEN (@CURRENTPAGE - 1) * @PAGESIZE + 1 AND @CURRENTPAGE * @PAGESIZE 

END 

это зависит от функции, называемой DistanceBetween (если экземпляр не поддерживает пространственный тип данных, то это часть необходимо заменить с изменением вашего собственного кода):

ALTER FUNCTION [dbo].[DistanceBetween] 
( 
    -- Add the parameters for the function here 
    @PIVOTE_LAT as float, 
    @PIVOTE_LNG as float, 
    @LAT as float, 
    @LNG as float 
) 

returns real 
as begin 
declare @distance real; 

declare @PIVOTE_POINT geography = geography::Point(@PIVOTE_LAT,@PIVOTE_LNG, 4326); 
declare @POINT geography = geography::Point(@LAT,@LNG, 4326); 

set @distance = @PIVOTE_POINT.STDistance(@POINT); 
return (@distance); 
end 
+0

Если OP не имеет встроенных функций географии, они могут использовать этот sql UDF: http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=81360 – hatchet

2

how would I further enhance it to sort the results by what's nearest to me?

Я считаю, что в SQL Server 2000, для сортировки по расчетному значению вы должны либо дублировать вычисления в ORDER BY пункте ORDER BY < the calculation> или вы можете сделать это:

 select FOO.a, FOO.b, FOO.myvalue 
     from 
     (
     select a, b, <some calculation> as myvalue 
     from T 
     where <some calculation> <= {some value} 
    ) as FOO 
     order by FOO.myvalue 

P.S. Но в более поздних версиях SQL вы можете сортировать по псевдониму столбца.

В любом случае у вас должен быть столбец, содержащий рассчитанное расстояние.

Смежные вопросы