ChatGPT解决这个技术问题 Extra ChatGPT

在 SQL Server 中存储坐标(经度/纬度,来自谷歌地图)的最佳方式是什么?

我正在 SQL Server 2008 中设计一个表,该表将存储用户列表和谷歌地图坐标(经度和纬度)。

我需要两个字段,还是可以用 1 个字段完成?

用于存储此类数据的最佳(或最常见)数据类型是什么?


C
Community

公平警告!在接受使用 GEOGRAPHY 类型的建议之前,请确保您不打算使用 Linq 或实体框架来访问数据,因为它不受支持(截至 2010 年 11 月),您会很难过!

2017 年 7 月更新对于现在阅读此答案的人来说,它已经过时,因为它指的是过时的技术堆栈。有关更多详细信息,请参阅评论。


由于发布了原始答案,我发现这篇文章 jasonfollas.com/blog/archive/2010/02/14/… 讨论了一种可能的解决方法。
警告不再有效。 EF 现在支持地理类型。
Nerveless EF 确实支持空间类型,它使用不同的类型设置到 WCF 数据服务,因此不兼容
例如,休眠 5 空间仍然不存在 :(
公平警告仍适用 Entity Framework Core 2.0 github.com/aspnet/EntityFrameworkCore/issues/1100
t
trejder

看看 SQL Server 2008 中引入的新空间数据类型。它们专为此类任务而设计,使索引和查询更加容易和高效。

更多信息:

MS TechNet:SQL Server 2008 空间数据类型,

MSDN:使用空间数据(数据库引擎)。


p
powtac

我不知道 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 ;

这个问题清楚地说明了 SQL Server,而不是 MySQL。而且您当然不希望像这样只有纬度和经度的表格。
同意 - 不好的答案。使用新的 GEOGRAPHY 空间类型。
由于精度问题,我不会使用浮点数。使用小数(9,6)。
即使在 SQL 2014 中使用高密度索引,也存在 latlng 优于 georgraphy 的实际情况。例如:find all point is with a rectangle。只是我不确定,我看到谷歌地图现在使用 7 位而不是 6 位数字?
j
jaxxbo

我这样做的方式:我存储纬度和经度,然后我有第三列,它是第一列的自动派生地理类型。该表如下所示:

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 目的。


非常适合我正在寻找的东西,你有任何关于曲目/线条的东西吗
根据您的情况,另一种也可以工作的方法是存储经纬度,然后在运行时动态创建地理对象。
好主意,但请注意,如果这是某人的意图,您不能在计算列上创建空间索引。
@hvaughan3 我认为如果你将其设为持久计算列,你可以。
谢谢和+1,你的回答帮助了我。但我认为使用 Point 而不是 STGeomFromText 会更好。例如:[geography]::Point([Latitude], [Longitude], 4326)
R
R. Lawson

我讨厌与那些说“这是一种新型,让我们使用它”的人相反。新的 SQL Server 2008 空间类型有一些优点 - 即效率,但您不能盲目地说总是使用该类型。这实际上取决于一些更大的问题。

例如,集成。这种类型在 .Net 中有一个等价的类型——但是互操作呢?支持或扩展旧版本的 .Net 怎么样?将这种跨服务层的类型暴露给其他平台怎么样?数据的规范化怎么样 - 也许您对 lat 或 long 作为独立的信息片段感兴趣。也许您已经编写了复杂的业务逻辑来处理 long/lat。

我并不是说你不应该使用空间类型——在很多情况下你应该。我只是说你应该在走这条路之前问一些更关键的问题。为了让我最准确地回答你的问题,我需要更多地了解你的具体情况。

单独存储 long/lat 或以空间类型存储都是可行的解决方案,根据您自己的情况,一种可能比另一种更可取。


至少自 2000 年代以来,GIS 和空间数据处理具有悠久的历史和标准的文本二进制表示。如果您不使用空间类型和标准表示,您最终会遇到您提到的所有问题
P
Pure.Krome

您要做的是将纬度和经度存储为新的 SQL2008 空间类型 -> 地理。

这是一张桌子的屏幕截图,我有。

alt text http://img20.imageshack.us/img20/6839/zipcodetable.png

在此表中,我们有两个存储地理数据的字段。

边界:这是作为邮政编码边界的多边形

CentrePoint:这是表示该多边形视觉中点的纬度/经度点。

您想将其作为 GEOGRAPHY 类型保存到数据库的主要原因是,您可以利用它的所有 SPATIAL 方法 -> 例如。多边形中的点、两点之间的距离等。

顺便说一句,我们还使用 Google 的 Maps API 来检索经纬度数据并将其存储在我们的 Sql 2008 DB 中——所以这种方法确实有效。


如果您还没有使用 2008 怎么办,或者如果您使用 SQLCE 怎么办?后者不支持 GEOGRAPHY 类型...
如果 SqlCE 或 < 2008 支持二进制,则可以将结果存储为 varbinary,然后使用空间工具库 dll 对 .NET 代码中的这种二进制数据表示进行空间计算。不是最好的解决方案,但仍然是一些问题的可能解决方案。 (用于 sql 空间的 nuget .. 获取该 dll)。
呃 :( 什么都不感谢 imageshack。我已经很多年没有使用 IS 了 :( imgur.com 一路!
-1,没有图像,这个答案是不完整的。请考虑将其替换为新图像或文本表格描述,或删除此答案。
R
Rosstified

SQL Server 支持空间相关信息。您可以在 http://www.microsoft.com/sqlserver/2008/en/us/spatial-data.aspx 中查看更多信息。

或者,您可以将信息存储为两个基本字段,通常浮点数是大多数设备报告的标准数据类型,并且在一英寸或两英寸内足够准确 - 对于谷歌地图来说已经足够了。


D
DhruvJoshi

注意:这是基于最近的 SQL 服务器、.NET 堆栈更新的最新答案

谷歌地图中的纬度和经度应在地理数据类型下存储为 SQL 服务器中的点(注意大写 P)数据。

假设您当前的数据以 varchar 形式存储在表 Sample 中的列 latlon 下,以下查询将帮助您转换为地理

alter table Sample add latlong geography
go
update Sample set latlong= geography::Point(lat,lon,4326)
go

PS:下次当您使用地理数据在此表上进行选择时,除了“结果”和“消息”选项卡外,您还将获得如下所示的“空间结果”选项卡以进行可视化

https://i.stack.imgur.com/lsYVn.png


O
Ogglas

如果您使用的是 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);
    }
}

https://stackoverflow.com/a/25563269/3850405


K
Kristen

如果您只是要将它替换为一个 URL,我想一个字段会这样做 - 所以您可以形成一个类似的 URL

http://maps.google.co.uk/maps?q=12.345678,12.345678&z=6

但由于它是两条数据,我会将它们存储在单独的字段中


这是我的情况。我只需要将坐标存储在一个字段中并用逗号分隔。我认为可以使用 TEXT 作为字段类型。你怎么看?
G
Graviton

将两者都存储为浮点数,并在它们上使用唯一的关键字.i.em

create table coordinates(
coord_uid counter primary key,
latitude float,
longitude float,
constraint la_long unique(latitude, longitude)
);

确保只有一组唯一的纬度和经度对。您不想在表中存储坐标 {0,0} 两次,不是吗?
您可能根本不希望有这样一个单独的坐标表,尤其是在唯一性约束的情况下,处理两个位置引用同一点的情况是一个维护噩梦,更不用说清理未引用的行了。
> 您可能根本不希望有这样一个单独的坐标表 - 一点也不?绝不?您将如何将其存储在 1 个字段中?数百万人不使用 SQL 2008 Spatial 类型呢?
有这样的限制是一个糟糕的决定。假设 Bob 住在 House A,并将搬到 House B,即 Alice 曾经居住的房子。很快 Bob 将无法保存他的地址(位置),因为 Alice 还没有更新她的地址(或者永远不会更新)。
@Sally - 他不是这么说的。阅读他的评论。他说没有理由将一对值存储在单独的表中。只需将 lat/long 放在原始表上,并节省第二个表和所有 JOINS 的开销。