2

我听说 SQL Server 现在支持地理之类的东西。是否可以从经度/纬度获得城市?我搜索了很多但找不到任何东西?

4

3 回答 3

7

您需要加载一些带有城市位置的数据——地名(您可能想要cities15000.zip)或自然地球(人口稠密的地方)可能是开始的好地方。

CREATE TABLE cities ( 
  name VARCHAR(200) PRIMARY KEY,
  location GEOGRAPHY, 
);
CREATE SPATIAL INDEX idx_cities_location ON cities(location);

INSERT INTO cities (name, location) VALUES
  ('Auckland', geography::STGeomFromText('POINT(174.7833 -36.85)', 4326)),
  ('London', geography::STGeomFromText('POINT(-0.1062 51.5171)', 4326))
;
  • 注意所有坐标的顺序是(Longitude Latitude)
  • 空间索引使其快速。
  • 4326 是基本经度/纬度的坐标系统代码。

然后要找到离给定位置最近的城市,您需要这样的查询:

DECLARE @g geography = 'POINT(103.75 1.3667)';
SELECT TOP(1) name FROM cities
WHERE location.STDistance(@g) IS NOT NULL
ORDER BY location.STDistance(@g);

SQL Server 文档中的更多示例:

于 2012-12-05T05:51:37.470 回答
4

您描述的功能称为“反向地理编码” - 采用纬度/经度坐标,并返回离该位置最近的地点的名称。(地理编码是相反的——提供地名以检索相关的纬度/经度坐标)。

您当然可以构建一个使用 SQL Server 作为后端数据库的反向地理编码服务,但没有任何内置功能可提供此类功能。

如果您只是想对一组现有数据进行反向地理编码,而不是在 SQL Server 中创建此功能,您可能会发现使用现有 Web 服务更容易。例如,地名 findNearbyPlaceName 有一个 REST 接口,您可以通过以下 URL 模板访问该接口:

http://api.geonames.org/findNearbyPlaceName?lat=52.62&lng=1.28&username=demo

此示例从 geonames 数据库返回与请求的 lat/lng 坐标 (52.62,1.28) 最接近的已知实体的信息,如下所示:

<geonames>
  <geoname>
    <toponymName>Norwich</toponymName>
    <name>Norwich</name>
    <lat>52.62783</lat>
    <lng>1.29834</lng>
    <geonameId>2641181</geonameId>
    <countryCode>GB</countryCode>
    <countryName>United Kingdom</countryName>
    <fcl>P</fcl>
    <fcode>PPLA2</fcode>
    <distance>1.51318</distance>
  </geoname>
</geonames>
于 2012-12-06T12:09:20.997 回答
2

对于空间函数,您需要 SQL 2008 或更高版本。

要做的第一件事是获取书籍/电子书:Alastair Aitchison 的 SQL Server 开始空间。他有一个 SQL 2008 和 2012 版本。他是那里的顶级大师之一。另一个是“空间戴夫”。披露:不,我没有得到一毛钱推荐阿利斯泰尔的书。我在 GreatData.com 工作并使用了 2008 年的书,当时我对 SQL 知之甚少,对映射一无所知,并且能够在短时间内变得相当精通,因为这本书非常好。

接下来,您需要加载城市边界。这些是 ESRI Shapefile 格式,您可以在 NationalAtlas.gov(免费地图文件的重要来源)上免费找到它们。

您需要了解只有较大的城市才有地图边界文件。有了边界,您可以使用 STIntersects() 或其他方法来确定您拥有的纬度/经度坐标是否在城市范围内。

对于较小的城镇,您只会得到一个纬度/经度点。您可以使用“最近邻居”逻辑(也在书中)来确定最近的城市或城镇,但无法确定它是否在城镇范围内。

于 2012-12-12T03:44:24.503 回答