【发布时间】:2010-10-07 19:17:47
【问题描述】:
我正在 SQL Server 2008 中设计一个表,该表将存储用户列表和 Google 地图坐标(经度和纬度)。
我需要两个字段,还是可以用 1 个字段完成?
用于存储此类数据的最佳(或最常见)数据类型是什么?
【问题讨论】:
标签: sql-server sql-server-2008 latitude-longitude spatial
我正在 SQL Server 2008 中设计一个表,该表将存储用户列表和 Google 地图坐标(经度和纬度)。
我需要两个字段,还是可以用 1 个字段完成?
用于存储此类数据的最佳(或最常见)数据类型是什么?
【问题讨论】:
标签: sql-server sql-server-2008 latitude-longitude spatial
公平警告! 在接受使用 GEOGRAPHY 类型的建议之前,请确保您不打算使用 Linq 或实体框架来访问数据,因为它不受支持(截至 2010 年 11 月)并且你会难过的!
2017 年 7 月更新
对于那些现在阅读此答案的人来说,它已经过时了,因为它指的是过时的技术堆栈。有关详细信息,请参阅 cmets。
【讨论】:
查看 SQL Server 2008 中引入的新空间数据类型。它们专为此类任务而设计,使索引和查询更加容易和高效。
更多信息:
【讨论】:
我不知道 SQL Server 的答案,但是...
在MySQL中保存为FLOAT( 10, 6 )
这是来自Google developer documentation的官方推荐。
CREATE TABLE `coords` (
`lat` FLOAT( 10, 6 ) NOT NULL ,
`lng` FLOAT( 10, 6 ) NOT NULL ,
) ENGINE = MYISAM ;
【讨论】:
lat 和lng 优于georgraphy 的实际情况,即使在SQL 2014 中使用高密度索引也是如此。例如:find all point is with a rectangle。只是我不确定,我看到 Google 地图现在使用 7 位而不是 6 位?
我这样做的方式:我存储 latitude 和 longitude,然后我有第三列,它是第一列的自动派生地理类型。该表如下所示:
CREATE TABLE [dbo].[Geopoint]
(
[GeopointId] BIGINT NOT NULL PRIMARY KEY IDENTITY,
[Latitude] float NOT NULL,
[Longitude] float NOT NULL,
[ts] ROWVERSION NOT NULL,
[GeographyPoint] AS ([geography]::STGeomFromText(((('POINT('+CONVERT([varchar](20),[Longitude]))+' ')+CONVERT([varchar](20),[Latitude]))+')',(4326)))
)
这使您可以灵活地对 geoPoint 列进行空间查询,并且您还可以根据需要检索纬度和经度值,以用于显示或提取以用于 csv 目的。
【讨论】:
Point 而不是STGeomFromText 会更好。例如:[geography]::Point([Latitude], [Longitude], 4326).
我讨厌与那些说“这是一种新类型,让我们使用它”的人相反。新的 SQL Server 2008 空间类型有一些优点 - 即效率,但是您不能盲目地说总是使用该类型。这实际上取决于一些更大的问题。
例如,集成。这种类型在 .Net 中有一个等价的类型——但是互操作呢?支持或扩展旧版本的 .Net 怎么样?将这种跨服务层的类型暴露给其他平台怎么样?数据的规范化怎么样 - 也许您对 lat 或 long 作为独立的信息片段感兴趣。也许您已经编写了复杂的业务逻辑来处理 long/lat。
我并不是说您不应该使用空间类型 - 在许多情况下您应该使用。我只是说你应该在走这条路之前问一些更关键的问题。为了最准确地回答您的问题,我需要更多地了解您的具体情况。
单独存储 long/lat 或以空间类型存储都是可行的解决方案,根据您自己的情况,一种可能比另一种更可取。
【讨论】:
您要做的是将纬度和经度存储为新的 SQL2008 空间类型 -> GEOGRAPHY。
这是一张桌子的屏幕截图,我有。
alt text http://img20.imageshack.us/img20/6839/zipcodetable.png
在这个表中,我们有两个存储地理数据的字段。
您想要将其作为 GEOGRAPHY 类型保存到数据库的主要原因是,您可以利用所有 SPATIAL 方法关闭它 -> 例如。多边形中的点、两点之间的距离等。
顺便说一句,我们还使用 Google 的 Maps API 来检索经纬度数据并将其存储在我们的 Sql 2008 DB 中——所以这种方法确实有效。
【讨论】:
SQL Server 支持空间相关信息。您可以在http://www.microsoft.com/sqlserver/2008/en/us/spatial-data.aspx 看到更多信息。
或者,您可以将信息存储为两个基本字段,通常浮点数是大多数设备报告的标准数据类型,并且在 1 英寸或 2 英寸范围内足够准确 - 对于 Google 地图来说已经足够了。
【讨论】:
注意:这是基于最近的 SQL 服务器、.NET 堆栈更新的最新答案
谷歌地图中的纬度和经度应在地理数据类型下存储为 SQL 服务器中的点(注意大写 P)数据。
假设您当前的数据以 varchar 形式存储在表 Sample 中,列在 lat 和 lon 下,下面的查询将帮助您转换为地理
alter table Sample add latlong geography
go
update Sample set latlong= geography::Point(lat,lon,4326)
go
PS:下次当您使用地理数据在此表上进行选择时,除了“结果”和“消息”选项卡外,您还将获得如下所示的“空间结果”选项卡以进行可视化
【讨论】:
如果您使用的是 Entity Framework 5 DbGeography。来自 MSDN 的示例:
public class University
{
public int UniversityID { get; set; }
public string Name { get; set; }
public DbGeography Location { get; set; }
}
public partial class UniversityContext : DbContext
{
public DbSet<University> Universities { get; set; }
}
using (var context = new UniversityContext ())
{
context.Universities.Add(new University()
{
Name = "Graphic Design Institute",
Location = DbGeography.FromText("POINT(-122.336106 47.605049)"),
});
context. Universities.Add(new University()
{
Name = "School of Fine Art",
Location = DbGeography.FromText("POINT(-122.335197 47.646711)"),
});
context.SaveChanges();
var myLocation = DbGeography.FromText("POINT(-122.296623 47.640405)");
var university = (from u in context.Universities
orderby u.Location.Distance(myLocation)
select u).FirstOrDefault();
Console.WriteLine(
"The closest University to you is: {0}.",
university.Name);
}
https://msdn.microsoft.com/en-us/library/hh859721(v=vs.113).aspx
我开始使用DbGeography 时遇到的问题是coordinateSystemId。有关以下代码的出色解释和来源,请参阅下面的答案。
public class GeoHelper
{
public const int SridGoogleMaps = 4326;
public const int SridCustomMap = 3857;
public static DbGeography FromLatLng(double lat, double lng)
{
return DbGeography.PointFromText(
"POINT("
+ lng.ToString() + " "
+ lat.ToString() + ")",
SridGoogleMaps);
}
}
【讨论】:
如果您只是要将它替换为一个 URL,我想一个字段会这样做 - 这样您就可以形成一个类似的 URL
http://maps.google.co.uk/maps?q=12.345678,12.345678&z=6
但由于它是两条数据,我会将它们存储在单独的字段中
【讨论】:
将两者都存储为浮点数,并在它们上使用唯一的关键字。i.em
create table coordinates(
coord_uid counter primary key,
latitude float,
longitude float,
constraint la_long unique(latitude, longitude)
);
【讨论】:
House A,并将搬到 House B,即 Alice 曾经居住的房子。很快 Bob 将无法保存他的地址(位置),因为 Alice 还没有更新她的地址(或者永远不会更新)。