SQL Server 2008 添加了一些很酷的新空间类型,并为 SQL 开发人员提供了很多更强大的空间数据处理方法,但我仍然不知道如何有效地返回,例如,仅返回 ## 英里半径内的位置一长串邮政编码(20 到 15000 个不同的邮政编码)。
有没有简单的方法来做到这一点?想到的唯一可能的解决方案似乎有点可怕,因为创建了 Cartiasian 乘积,因此计算量大得离谱......
如果有帮助,我擅长创建 CLR SP 和函数(我认为它会......)。
我不太关心如何找到 2 点(或地理类型)之间的距离,而是“给定位置是否在所提供列表中任何邮政编码(地理点)的 ## 英里范围内?”这里的复杂部分是要搜索的 zip 列表。
谢谢。
最佳答案
我必须实现地理定位搜索,经过大量研究后我决定使用 sql2008 地理。您需要一个填有经/纬度的邮政编码表。该表应如下所示:
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。然后我运行以下脚本将数据插入我的邮政编码表并创建空间索引。 (我必须添加自己的 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);
最后,我创建了一个接受纬度/经度并返回特定范围内的所有邮政编码的函数。因为它使用空间索引,所以速度非常快。
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
我知道这不是您要找的东西,但可以将其转换为您的目的。我发现使用邮政编码比城市更有效和准确,因为城市可以跨越许多邮政编码,因此返回给最终用户的数据是错误的。
这一切都非常以美国为中心,但可以很容易地转换为国际使用。我计划在未来的某个时候这样做,但还没有这个需要。
关于c# - 如何返回邮政编码列表 ## 英里半径内的所有实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3919878/