SQL Server:查找最近的位置

时间:2013-04-30 18:30:01

标签: sql-server

鉴于以下SQL返回基于给定城市的机场列表,我将如何进一步增强它以按离我最近的方式对结果进行排序?它看起来应该很简单,但它让我望而却步。

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;

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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的更高版本中,您可以对列别名进行排序。

在任何情况下,您都必须有一列来包含计算的距离。