SQL Serverに座標(Googleマップからの経度/緯度)を保存するための最良の方法は何ですか?


103

SQL Server 2008で、ユーザーのリストとGoogleマップの座標(経度と緯度)を格納するテーブルを設計しています。

2つのフィールドが必要ですか、それとも1つで実行できますか?

この種のデータを格納するために使用するのに最適な(または最も一般的な)データ型は何ですか?

回答:



63

公正警告!GEOGRAPHYタイプを使用するためのアドバイスを受ける前に、LinqまたはEntity Frameworkを使用してデータにアクセスすることを計画していないことを確認してください(2010年11月現在)。

2017年7月の更新

現在この回答を読んでいる人にとっては、時代遅れのテクノロジースタックに言及しているため、時代遅れです。詳細についてはコメントを参照してください。


1
元の回答が投稿されたので、この記事jasonfollas.com/blog/archive/2010/02/14/…で可能な回避策について説明しました。
ノーマンH

56
警告は無効になりました。EFは地理タイプをサポートするようになりました。
Marcelo Mason

1
Nerveless EFは空間タイプをサポートします。WCFデータサービスに設定された異なるタイプを使用するため、互換性がありません
abatishchev

1
hibernate 5 spatialはまだ例ではありません:(
Eugene

1
公正な警告は引き続きEntity Framework Core 2.0 github.com/aspnet/EntityFrameworkCore/issues/1100
ono2012

29

SQL Serverの答えはわかりませんが...

MySQLのようにそれを保存FLOAT( 10, 6 )

これは、Googleデベロッパードキュメントの公式の推奨事項です。

CREATE TABLE `coords` (
  `lat` FLOAT( 10, 6 ) NOT NULL ,
  `lng` FLOAT( 10, 6 ) NOT NULL ,
) ENGINE = MYISAM ;

19
この質問は、MySQLではなくSQL Serverを明確に述べています。そして、あなたは確かにそのような緯度と経度だけのテーブルが欲しくないでしょう。
araqnid 2009年

2
同意-悪い答え。新しいGEOGRAPHY空間タイプを使用します。
Pure.Krome 2009年


14
精度の問題のため、floatは使用しません。decimal(9,6)を使用してください。
カプタン2012年

実際の例があるlatlngアウトパフォームgeorgraphyも、例えばSQL 2014での高密度インデックスとは、すべての点が長方形をwithingている見つけます。よくわかりませんが、Googleマップで6桁ではなく7桁が使用されるようになりました。
2015年

22

私が行う方法:緯度経度を保存してから、3番目の列があり、これは最初の2列の自動派生地理タイプです。テーブルは次のようになります。

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の目的で表示または抽出することもできます。


私が探していたものに最適です、トラック/ラインに何かありますか
aggie

シナリオに応じて機能する別のアプローチは、経度と緯度を保存し、実行時に動的に地理オブジェクトを動的に作成することです。
Zapnologica 2016年

1
すばらしいアイデアですが、誰かの意図で計算カラムに空間インデックスを作成できないことに注意してください。
hvaughan3 2016年

1
@ hvaughan3 永続化された計算列にできればできると思います。
NickG 2016

2
おかげで、あなたの答えは私を助けました。ただし、のPoint代わりに使用した方がよいと思いますSTGeomFromText。次に例を示します[geography]::Point([Latitude], [Longitude], 4326)
default.kramer 2016年

21

「ここは新しいタイプです、使ってみよう」と言った人に逆らうのは嫌いです。新しいSQL Server 2008の空間タイプにはいくつかの長所があります。つまり効率ですが、常にそのタイプを常に使用するとは言い切れません。それは実際にはいくつかの大きな問題に依存します。

例として、統合。このタイプには.Netで同等のタイプがありますが、相互運用性についてはどうですか?古いバージョンの.Netのサポートまたは拡張についてはどうですか?このタイプをサービス層全体で他のプラットフォームに公開するのはどうですか?データの正規化についてはどうでしょうか。おそらく、緯度または経度のスタンドアロン情報に興味があります。多分、あなたはすでにlong / latを処理するための複雑なビジネスロジックを書いています。

空間タイプを使用するべきではないと言っているわけではありません-多くの場合、使用する必要があります。その道を進む前に、もっと重要な質問をするべきだと言っているだけです。私があなたの質問に最も正確に答えるには、あなたの特定の状況についてもっと知る必要があります。

long / latを個別に、または空間タイプで格納することはどちらも実行可能なソリューションであり、状況によっては一方が他方よりも望ましい場合があります。


GISと空間データ処理には長い歴史があり、少なくとも2000年代以降、標準のテキスト形式のバイナリ表現があります。空間タイプと標準表現を使用しないと、先に述べたすべての問題が発生します
Panagiotis Kanavos 2017

15

実行したいことは、緯度と経度を新しいSQL2008空間タイプとして保存することです->地理学。

これが私が持っているテーブルのスクリーンショットです。

代替テキストhttp://img20.imageshack.us/img20/6839/zipcodetable.png

この表には、地理データを格納する2つのフィールドがあります。

  • 境界:これは、郵便番号の境界であるポリゴンです
  • CentrePoint:これは、このポリゴンの視覚的な中点を表す緯度/経度のポイントです。

それをGEOGRAPHYタイプとしてデータベースに保存する主な理由は、それからすべてのSPATIALメソッドを利用できるようにするためです。ポリゴン内のポイント、2点間の距離など

ちなみに、GoogleのMaps APIを使用して緯度/経度データを取得し、それをSQL 2008 DBに保存しているため、このメソッドは機能します。


1
そして、2008にまだ参加していない場合、またはSQLCEを使用している場合はどうなりますか?後者はGEOGRAPHYタイプをサポートしていません...
fretje

3
SqlCEまたは<2008がバイナリをサポートしている場合、結果をvarbinaryに保存してから、空間ツールライブラリdllを使用して、.NETコードのこのバイナリデータ表現に対して空間計算を行うことができます。最善の解決策ではありませんが、いくつかの問題に対する可能な解決策です。(そのdllを取得するためのSQL空間の..のnuget)。
Pure.Krome

2
画像のリンクが壊れている
ブライアンデニー

urgh :(何もない画像のおかげで感謝。私は何年もISを使用していません:( imgur.comずっとずっと!
Pure.Krome

1
-1、この答えは画像なしでは不完全です。新しい画像またはテキストの表の説明に置き換えるか、この回答を削除することを検討してください。
Ilmari Karonen 2016年

11

SQL Serverは、空間関連情報をサポートしています。詳細については、http://www.microsoft.com/sqlserver/2008/en/us/spatial-data.aspxを参照してください

あるいは、情報を2つの基本的なフィールドとして保存できます。通常、floatはほとんどのデバイスによって報告される標準のデータ型であり、1〜2インチ以内で十分に正確です。これは、Googleマップには十分です。


2

:これは、最近のSQLサーバー、.NETスタックの更新に基づく最近の回答です

Googleマップの緯度と経度は、地理データタイプの下のSQLサーバーのポイント(大文字のPに注意)データとして保存する必要があります。

現在のデータがSample列の下のvarcharとしてテーブルに格納されていると仮定するlatlon、以下のクエリは地理に変換するのに役立ちます

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

PS:次回、地理データを使用してこのテーブルを選択すると、[結果とメッセージ]タブの他に、視覚化のために以下のような[空間結果]タブも表示されます

SSMS地理結果タブ


0

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


-4

URLに置き換えるだけの場合は、1つのフィールドで可能だと思います。そのため、次のようなURLを作成できます。

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

2つのデータなので、別々のフィールドに保存します


これは私のケースです。座標を1つのフィールドのみにコンマで区切って保存する必要があります。フィールドタイプとしてTEXTを使用できると思います。どう思いますか?
Amr 2017年

-10

両方をフロートとして保存し、それらに固有のキーワードを使用します。

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

緯度と経度のペアの一意のセットが1つだけであることを確認します。座標{0,0}をテーブルに2回格納したくないですか。
グラビトン

1
おそらく、このような個別の座標テーブルがまったく必要ないでしょう。特に、一意性の制約の場合、参照されていない行のクリーンアップは言うまでもなく、2つの場所が同じポイントを参照する場合の処理​​の悪夢です。
araqnid 09年

2
> おそらく、このような個別の座標テーブルをまったく使いたくないでしょう - まったくそうではありませんか?決して?それを1つのフィールドにどのように格納しますか?SQL 2008 Spatialタイプを使用していない何百万もの人々はどうですか?
サリー

2
そのような制約があることは悪い決断です。ボブがに住んでいてHouse AHouse Bアリスがかつて住んでいた家に移動するとします。すぐにボブは自分の住所(場所)を保存できなくなります。これは、アリスが彼女のアドレスをまだ更新していないか、更新しないためです。
jweyrich

@サリー-それは彼が言ったことではありません。彼のコメントを読んでください。彼は、値のペアを別のテーブルに格納する理由はないはずだと述べました。lat / longを元のテーブルに置くだけで、2番目のテーブルのオーバーヘッドとすべてのJOINSを節約できます。
NickG 2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.