Koordinatları (Google Haritalar'dan enlem / boylam) SQL Server'da depolamanın en iyi yolu nedir?


103

SQL Server 2008'de bir kullanıcı listesini ve bir Google Haritalar koordinatını (boylam ve enlem) depolayacak bir tablo tasarlıyorum.

İki alana ihtiyacım olacak mı yoksa 1 ile yapılabilir mi?

Bu tür verileri depolamak için kullanılacak en iyi (veya en yaygın) veri türü nedir?

Yanıtlar:



63

Adil Uyarı! GEOGRAPHY türünü kullanma tavsiyesini almadan önce, desteklenmediği için (Kasım 2010 itibariyle) verilere erişmek için Linq veya Entity Framework kullanmayı planlamadığınızdan emin olun ve üzüleceksiniz!

Temmuz 2017'yi güncelleyin

Bu yanıtı şimdi okuyanlar için, geçmiş teknoloji yığınına atıfta bulunduğu için geçersizdir. Daha fazla ayrıntı için yorumlara bakın.


1
Orijinal yanıt gönderildiği için jasonfollas.com/blog/archive/2010/02/14/… olası bir geçici çözümü tartışan bu makaleyi buldum .
Norman H

56
Uyarı artık geçerli değil. EF artık Coğrafya türlerini desteklemektedir.
Marcelo Mason

1
Sinirsiz EF, Uzamsal Türleri destekliyor, WCF Veri Hizmetlerine ayarlanmış farklı türler kullanıyor, bu nedenle uyumlu değil
abatishchev

1
hazırda bekletme 5 uzamsal hala örneğin :(
Eugene

1
Adil Uyarı hala Entity Framework Core 2.0 github.com/aspnet/EntityFrameworkCore/issues/1100
ono2012

29

SQL Server'ın cevabını bilmiyorum ama ...

In MySQL olarak kaydedinFLOAT( 10, 6 )

Bu, Google geliştirici belgelerinin resmi önerisidir .

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

19
Soru, MySQL'i değil, SQL Server'ı açıkça belirtir. Ve kesinlikle kendi başına enlem ve boylamın olduğu bir masa istemezsiniz.
araqnid

2
Kabul edildi - kötü cevap. Yeni GEOGRAPHY uzamsal türünü kullanın.
Pure.Krome


14
Hassasiyet sorunları nedeniyle float kullanmazdım. Ondalık (9,6) kullanın.
kaptan

SQL 2014'teki yüksek yoğunluklu dizinlerde bile nerede latve lngdaha iyi performans gösterdiği gerçek durumlar vardır georgraphy. Örneğin: tüm noktayı bul bir dikdörtgen kullanmaktır. Ancak emin değilim, Google Haritalar'ın artık 6 basamak yerine 7 kullandığını görüyorum.
Nenad

22

Bunu yapma şeklim: Enlem ve boylamı kaydediyorum ve ardından 1. iki sütunun otomatik olarak türetilmiş coğrafya türü olan üçüncü bir sütunum var. Tablo şuna benzer:

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))) 
)

Bu size geoPoint sütunundaki uzamsal sorguların esnekliğini sağlar ve ayrıca enlem ve boylam değerlerini csv amacıyla görüntülemek veya çıkarmak için ihtiyaç duyduğunuzda alabilirsiniz.


aradığım şey için harika, parçalar / çizgiler için bir şeyleriniz var mı
aggie

Senaryonuza bağlı olarak işe yarayabilecek başka bir yaklaşım da uzun ve enlemi depolamak ve ardından coğrafya nesnesini çalışma zamanında dinamik olarak yaratmaktır.
Zapnologica

1
Harika bir fikir, ancak birinin niyeti buysa, hesaplanan sütunlarda uzamsal dizinler oluşturamayacağınızı unutmayın.
hvaughan3

1
@ hvaughan3 Kalıcı bir hesaplanmış sütun yaparsanız yapabileceğinizi düşünüyorum .
NickG

2
Teşekkürler ve +1, cevabınız bana yardımcı oldu. Ama Pointbunun yerine kullanmanın daha iyi olacağını düşünüyorum STGeomFromText. Örneğin: [geography]::Point([Latitude], [Longitude], 4326).
default.kramer

21

"İşte yeni bir tip, kullanalım" diyenlere aykırı olmaktan nefret ediyorum. Yeni SQL Server 2008 uzamsal türlerinin bazı avantajları vardır - yani verimlilik, ancak körü körüne her zaman bu türü kullanın diyemezsiniz. Gerçekten bazı daha büyük resim sorunlarına bağlı.

Örnek olarak entegrasyon. Bu türün .Net'te eşdeğer bir türü vardır - peki ya birlikte çalışma? .Net'in eski sürümlerini desteklemeye veya genişletmeye ne dersiniz? Bu türü hizmet katmanında diğer platformlara göstermeye ne dersiniz? Verilerin normalleştirilmesine ne dersiniz - belki enlem veya bağımsız bilgi parçaları olarak uzun süredir ilgileniyorsunuz. Belki de uzun / lat ile başa çıkmak için karmaşık iş mantığı yazmışsınızdır.

Uzamsal türü kullanmamalısınız demiyorum - çoğu durumda kullanmalısınız. Sadece o yola girmeden önce daha kritik sorular sorman gerektiğini söylüyorum. Sorunuzu en doğru şekilde yanıtlayabilmem için özel durumunuz hakkında daha fazla bilgiye ihtiyacım var.

Uzun / lat ayrı ayrı veya uzamsal türde saklamak hem uygulanabilir çözümlerdir hem de kendi koşullarınıza bağlı olarak biri diğerine tercih edilebilir.


CBS ve mekansal veri işleme uzun bir geçmişe ve en azından 2000'lerden beri standart metinsel, ikili temsillere sahiptir. Eğer varsa hepsi ile Bahsettiğiniz sorunlar bitireceğiz yok uzamsal türleri ve standart gösterimleri kullanmak
Panagiotis Kanavos

15

Yapmak istediğiniz, Enlem ve Boylamı yeni SQL2008 Uzamsal tür -> COĞRAFYA olarak depolamaktır.

İşte elimde olan bir tablonun ekran görüntüsü.

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

Bu tabloda coğrafya verilerini depolayan iki alanımız var.

  • Sınır: bu, posta kodu sınırı olan çokgendir
  • CentrePoint: bu, bu çokgenin görsel orta noktasını temsil eden Enlem / Boylam noktasıdır.

Onu veritabanına bir GEOGRAPHY türü olarak kaydetmek istemenizin ana nedeni, daha sonra tüm SPATIAL yöntemlerinden yararlanabilmenizdir -> örn. Poly'de Nokta, İki nokta arasındaki mesafe, vb.

BTW, ayrıca enlem / boylam verilerini almak ve bunları Sql 2008 DB'mizde depolamak için Google'ın Haritalar API'sini kullanıyoruz - bu nedenle bu yöntem işe yarıyor.


1
Peki ya 2008'de değilseniz ya da SQLCE kullanıyorsanız ne olur? İkincisi, GEOGRAPHY türünü desteklemiyor ...
fretje

3
SqlCE veya <2008 ikiliyi destekliyorsa, sonuçları değişken ikili olarak depolamak ve ardından .NET kodunuzda bu ikili veri sunumuna karşı uzamsal hesaplamalar yapmak için Uzamsal araçlar kitaplığı dll'yi kullanmak mümkündür. En iyi çözüm değil, ancak yine de bazı sorunlara olası bir çözüm . (nuget for sql spatial .. o dll'yi kapmak için).
Pure.Krome

2
Resim bağlantısı kesildi
Bryan Denny

urgh :( hiç bir şey yapmadığın için teşekkürler. IS'yi yıllardır kullanmadım :( imgur.com!
Pure.Krome

1
-1, bu cevap resim olmadan eksiktir. Lütfen yeni bir resim veya metinsel bir tablo açıklaması ile değiştirmeyi veya bu yanıtı silmeyi düşünün.
Ilmari Karonen


2

NOT : Bu, son SQL sunucusu, .NET yığın güncellemelerine dayanan yeni bir cevaptır.

Google Haritalar'daki enlem ve boylam, coğrafi veri türü altında SQL sunucusunda Nokta (büyük P not edin) verisi olarak depolanmalıdır.

Mevcut verilerinizin bir tabloda Samplesütunların altında varchar olarak depolandığını latve lonaşağıdaki sorgunun coğrafyaya dönüştürmenize yardımcı olacağını varsayarsak

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

Not: Bir dahaki sefere bu tabloda coğrafya verileriyle bir seçim yaptığınızda, Sonuçlar ve Mesajlar sekmesinden ayrı olarak, görselleştirme için aşağıdaki gibi Mekansal sonuçlar sekmesi de alacaksınız.

SSMS coğrafi sonuçlar sekmesi


0

Entity Framework 5 kullanıyorsanız <kullanabilirsiniz DbGeography. MSDN'den örnek:

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

Mücadele ettiğim ve kullanmaya başladığım bir DbGeographyşeydi coordinateSystemId. Aşağıdaki koda ilişkin mükemmel bir açıklama ve kaynak için aşağıdaki yanıta bakın.

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

Eğer onu bir URL ile değiştirecekseniz, sanırım bir alan yapacaktır - böylece şöyle bir URL oluşturabilirsiniz

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

ama iki parça veri olduğu için onları ayrı alanlarda saklarım


Bu benim davam. Koordinatları tek bir alanda ve virgülle ayırarak saklamam gerekiyor. Alan türü olarak METİN kullanılabileceğini düşünüyorum. Ne düşünüyorsun?
Amr

-10

Her ikisini de kayan nokta olarak saklayın ve bunlarda benzersiz anahtar kelimeler kullanın. İ.em

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

Yalnızca 1 benzersiz enlem ve boylam çifti kümesi olduğundan emin olmak için. {0,0} koordinatını tablonuzda iki kez saklamak istemezsiniz, değil mi?
Graviton

1
Muhtemelen bunun gibi ayrı bir koordinat tablosuna sahip olmak istemezsiniz, özellikle de benzersizlik kısıtlamasıyla, iki konumun aynı noktaya başvurması durumunda bir bakım kabusu, başvurulmayan satırları temizlemekten bahsetmeye bile gerek yok.
araqnid

2
> Muhtemelen bunun gibi ayrı bir koordinat tablosuna sahip olmak istemezsiniz - Hiç de değil mi? Asla? Bunu 1 alanda nasıl saklarsınız? Milyonlarca kişi SQL 2008 Uzamsal tip KULLANMAYACAK?
Sally

2
Böyle bir kısıtlamaya sahip olmak kötü bir karardır. Farz edin ki Bob House A, House BAlice'in eskiden yaşadığı evde yaşıyor ve oraya taşınacak . Yakında Bob adresini (konumunu) kaydedemeyecek, çünkü Alice onun adresini henüz güncellemedi - ya da asla yapmayacak.
jweyrich

@Sally - o öyle demedi. Yorumunu okuyun. Bir çift değeri ayrı bir tabloda saklamak için hiçbir neden olmaması gerektiğini söyledi . Sadece enlem / boylam değerini orijinal masanın üzerine koyun ve ikinci bir masanın ek yükünü ve tüm BİRLEŞTİRMELERİ kaydedin.
NickG
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.