如何返回Zipcode列表的## Mile Radius内的所有实例

SQL Server 2008添加了一些很酷的新Spacial类型,并为SQL开发人员提供了更强大的操作空间数据的方法,但它仍然让我无法返回,例如,只返回长列表## mile半径范围内的位置拉链(20到15,000个不同的拉链码)。

有一个简单的方法吗? 想到的唯一可能的解决方案似乎有点可怕,因为创建了cartiasian产品,因此计算得非常多……

我擅长创建CLR SP和函数,如果这有帮助(我认为它会……)。

我不太关心如何找到2点(或地理类型)之间的距离,而不是“在提供的列表中任何一个zipcodes(地理点)的##里程内的给定位置?” 这里的复杂部分是要搜索的拉链列表。

谢谢。

我不得不实施地理定位搜索,经过大量研究后我决定使用sql2008地理。 您需要一个填充了lat / long的邮政编码表。 该表应如下所示:

CREATE TABLE [dbo].[PostalCodes]( [ID] [bigint] IDENTITY(1,1) NOT NULL, [StateID] [bigint] NOT NULL, [PostalCode] [varchar](10) NOT NULL, [Latitude] [decimal](16, 12) NULL, [Longitude] [decimal](16, 12) NULL, [GeographyLocation] [geography] NULL, [CreatedOn] [datetime] NOT NULL, [LastUpdated] [datetime] NOT NULL, [GeographyLocation_temp] [varchar](100) NULL, CONSTRAINT [PK_PostalCode] PRIMARY KEY CLUSTERED ( [ID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO 

我从GeoNames.org下载了一个国际邮政编码列表,并将其作为tmp_GeoNames导入。 然后我运行以下脚本将数据插入到我的zipcode表中并创建空间索引。 (我必须添加自己的StateID列并填充它,但您可以跳过该部分并将其从脚本中删除。)

 INSERT INTO PostalCodes (StateID, PostalCode, Latitude, Longitude) SELECT DISTINCT StateID, PostalCode, Latitude, Longitude FROM temp_GeoNames where stateID is not null UPDATE PostalCodes SET GeographyLocation_temp= 'POINT(' + CONVERT(VARCHAR(100),longitude) +' ' + CONVERT(VARCHAR(100),latitude) +')' UPDATE PostalCodes SET GeographyLocation = geography::STGeomFromText(GeographyLocation_temp,4326) CREATE SPATIAL INDEX SIndx_SpatialTable_geography_col1 ON PostalCodes(GeographyLocation); 

最后,我创建了一个接受lat / long的函数,并返回一定范围内的所有zipcodes。 因为它使用空间索引,所以速度非常快。

 CREATE FUNCTION [dbo].[PostalCode_SelectNearest] ( @Latitude [decimal](16, 12) ,@Longitude [decimal](16, 12) ,@RangeInMiles int ) RETURNS @PostalCodes Table (PostalCode varchar(10) PRIMARY KEY NOT NULL, DistanceInMiles FLOAT NULL) AS BEGIN --Create geography point based on Lat/Long passed ... careful, the values passed are reversed from normal thinking DECLARE @g geography; SET @g = geography::STGeomFromText('POINT(' + CONVERT(varchar,@Longitude) + ' ' + CONVERT(varchar,@Latitude) + ')', 4326); --Select the nearest Postal Codes INSERT INTO @PostalCodes (PostalCode, DistanceInMiles) SELECT PostalCode, GeographyLocation.STDistance(@g)/1609.344 as DistanceInMiles FROM PostalCodes WHERE GeographyLocation.STDistance(@g)<=(@RangeInMiles * 1609.344) RETURN; END 

我意识到这并不是你想要的,但可以转换成你的目的。 我发现使用zipcodes比城市更有效和准确,因为城市可以跨越许多邮政编码,因此返回对最终用户来说错误的数据。

这一切都以美国为中心,但很容易转换为国际使用。 我计划在未来的某个时候做这个,但还没有必要。

还要考虑这需要多么准确……对于小半径,(不需要大圆数学),只需将一个方形内的所有位置都放在一边多英里……这可以如果你有每个邮政编码的纬度和经度,只需要一个filter,无需任何计算。 并且返回的行数将被关闭(它将太多)仅为因子1-pi / 4,仅为约21%

foreach给定位置(Tgt lat / long)
– 假设半径在海里(6080英尺),
纬度和经度以总分钟计算
(即30度,10分钟= 1810分钟)

然后:

 Select * From theTable Where Latitude Between TgtLat - radius And TgtLat + radius And Longitude Between TgtLong - radius/Cos(TgtLat) And TgtLong + radius/Cos(TgtLat) 

好吧,我确实有一个sql函数,可以为你执行那些实际上并不那么慢的可怕计算。 但是这里有一个链接以及如何使用sql 2008中的新function执行查询: http : //msdn.microsoft.com/en-us/magazine/dd434647.aspx

编辑:更多链接:

http://blogs.lessthandot.com/index.php/DataMgmt/DataDesign/sql-server-2008-proximity-search-with-th

查看GeoNames Webservice。 我用过这个,效果很好。

http://www.geonames.org/export/client-libraries.html

我已经完成了与Oracle Spatial非常相似的事情,所以我不熟悉MSSQL的空间特性,因此我的答案很简单:

我将假设您拥有表示包含每个邮政编码的多边形的数据,您所要做的就是获取邮政编码列表,组合他们的多边形,然后询问组合多边形内的所有记录或在其边缘x英里内。 某些空间包具有“多重”类型,允许您在非连续区域(在您的情况下为非相邻邮政编码)中进行组合和操作。

如果你拥有的只是邮政编码的中心点,你可以做同样的事情:组合点并寻找x英里内的任何东西。 这里的缺陷是一些邮政编码可能非常大,你会丢失一些符合你标准但不在中心点x英里范围内的记录。

它听起来很毛茸茸,但用于空间数据的索引系统非常有效。

HTH。

无论您决定采用何种解决方案,您都需要一个邮政编码数据库。 这是一个 ,下载并将其导入表格。