2009-07-28 5 views
227

Wenn Sie Breiten- oder Längengraddaten in einer ANSI SQL-kompatiblen Datenbank speichern, welcher Datentyp wäre am besten geeignet? Soll float oder decimal oder ... verwendet werden?Welcher Datentyp wird beim Speichern von Breiten- und Längenangaben in SQL-Datenbanken verwendet?

Mir ist bekannt, dass Oracle, MySql und SQL Server einige spezielle Datentypen speziell für den Umgang mit Geodaten hinzugefügt haben, aber ich bin interessiert, wie Sie die Informationen in einer "plain vanilla" SQL-Datenbank speichern würden.

+18

Wie ist das eine doppelte Frage? Er fragt eindeutig nach der SQL-Datenbank, wenn die andere Frage (und die Antworten dort auch) speziell auf MySQL eingehen. – Atul

+4

Atul hat recht, es ist nicht die gleiche Frage auch, weil der andere angibt, dass Berechnungen auf lat/lng gemacht werden. Ich habe gerade gemerkt, dass meine Antwort von der anderen hier am besten geeignet ist, also schaut bitte nach: http://StackOverflow.com/a/25120203/1226018 – Simon

+0

Ich werde Jahre später mitspielen. Atul und Simon haben Recht. Dies sind funktional verschiedene Fragen. Wenn Sie dies als Duplikat markieren, entspricht das der Aussage, dass die Frage, wie Sie einen Datensatz in einer Datenbank mit C# und Python persistieren, Duplikate sind. –

Antwort

331

Decimal(9,6)

Wenn Sie Genauigkeit und Skalierung Parameter nicht gewohnt sind, hier ist ein Format-String-visuelle:

###.######

+19

+1: Vermeiden Sie abrunden Fehler Seltsamkeit mit einer festen Anzahl von Dezimalstellen. –

+9

Für ihre Zwecke schlägt Wikipedia vor: "Übermäßige Präzision vermeiden (0,0001 ° ist <11 m, 1 '' ist <31 m)." http://en.wikipedia.org/wiki/Wikipedia:Objecting_geographic_coordinates Um meine Felder besonders präzise zu machen, habe ich auch entschieden, sechs Stellen rechts von der Dezimal-Marke zu verwenden, und drei auf der linken Seite. Ich bin froh, dass diese Antwort bestätigt, dass es eine gute Entscheidung war. –

+1

Überprüfen Sie die letzte Antwort in diesem [Artikel] (http://groups.google.com/group/google-maps-api/browse_thread/thread/b928b5fbc5351821). Der Benutzer William erklärt sehr gut, was mit Präzision passiert, während Sie weit vom Äquator entfernt sind. – Throoze

5

Wir verwenden Schwimmer, aber jeden Geschmack von numerischen mit sollte 6 Dezimalstellen auch Arbeit.

+27

Eine Berechnung könnte zusätzliche Ziffern einführen, die nur Rauschen wären. Auch die Dezimal-zu-Binär-Umwandlung macht die letzte Dezimalstelle verdächtig und möglicherweise falsch. Für einige Zwecke gut. Miserabel für die Navigation. –

+4

S> Lott, ich würde deinen Kommentar eine Million Mal auffrischen, wenn ich könnte, verwende niemals float für lat und long. – HLGEM

+1

Ich denke nicht, dass das Floaten eine Down-Rate verdient - du hast mich dazu gebracht, anderswo nach einer Antwort zu suchen: http://stackoverflow.com/questions/551894/whats-the-best-way-to-store -co-ordinates-longitude-latitude-from-google-maps – Keith

1

Ich würde eine Dezimalstelle mit der richtigen Genauigkeit für Ihre Daten verwenden.

1

Ich denke, es hängt von den Operationen ab, die Sie am häufigsten durchführen müssen.

Wenn Sie den vollen Wert als Dezimalzahl benötigen, verwenden Sie die Dezimalzahl mit der entsprechenden Genauigkeit und Skalierung. Float ist weit jenseits Ihrer Bedürfnisse, glaube ich.

Wenn Sie häufig zu/von degºmin'sec "-Fraktion Notation Umwandlung werde, halte ich würde jeden Wert als Integer-Typ Speichern (smallint, tinyint, tinyint, smallint?).

1

Nun, Sie gefragt, wie Breite/Länge und ist meine Antwort zu speichern: Sie verwenden könnte prüfen Sie für Georeferenzen nicht, die WGS 84 (in Europa ETRS 89), wie es der Standard ist

Aber das Detail beiseite verwendete ich ein User Defined Type. in den Tagen, bevor SQL 2008 endlich die Unterstützung von geo enthält

2

In Vanille Oracle, das Feature ca In LOCATOR (eine verkrüppelte Version von Spatial) müssen die Koordinatendaten unter Verwendung des Datentyps NUMBER (keine Genauigkeit) gespeichert werden. Wenn Sie versuchen, funktionsbasierte Indizes zu erstellen, um räumliche Abfragen zu unterstützen, wird dies anders aussehen.

2

Sie können ein leicht speichern lat/lon Dezimalzahl in einem unsigned Integer-Feld, anstatt sie nach oben in einer ganzen Zahl und Dezimalteil Aufspalten und diejenigen separat als etwas hier vorgeschlagene Speicherung mit der folgenden Umrechnungsalgorithmus:

als mysql Funktion gespeichert:

CREATE DEFINER=`r`@`l` FUNCTION `PositionSmallToFloat`(s INT) 
RETURNS decimal(10,7) 
DETERMINISTIC 
RETURN if(((s > 0) && (s >> 31)) , (-(0x7FFFFFFF - 
(s & 0x7FFFFFFF)))/600000, s/600000) 

und

CREATE DEFINER=`r`@`l` FUNCTION `PositionFloatToSmall`(s DECIMAL(10,7)) 
RETURNS int(10) 
DETERMINISTIC 
RETURN s * 600000 

zurück, die in einem unsigned int (10) gespeichert werden muss, funktioniert dies in MySQL sowie in SQLite, die typenlos ist.

durch Erfahrung, finde ich, dass dies wirklich schnell funktioniert, wenn alles, was Sie brauchen, um Koordinaten zu speichern und abrufen, um etwas Mathe mit zu tun.

in PHP diese zwei Funktionen aussehen

function LatitudeSmallToFloat($LatitudeSmall){ 
    if(($LatitudeSmall>0)&&($LatitudeSmall>>31)) 
    $LatitudeSmall=-(0x7FFFFFFF-($LatitudeSmall&0x7FFFFFFF))-1; 
    return (float)$LatitudeSmall/(float)600000; 
} 

und wieder zurück:

function LatitudeFloatToSmall($LatitudeFloat){ 
    $Latitude=round((float)$LatitudeFloat*(float)600000); 
    if($Latitude<0) $Latitude+=0xFFFFFFFF; 
    return $Latitude; 
} 

Dieser einige Vorteile hat in der Bezeichnung der Erstellung von beispielsweise Memcached eindeutige Schlüssel mit ganzen Zahlen als auch hinzugefügt. (zB um ein Geocode-Ergebnis zwischenzuspeichern). Ich hoffe, dass dies der Diskussion einen Mehrwert verleiht.

Eine weitere Anwendung könnte, wenn Sie ohne GIS-Erweiterungen sind und nur ein paar Millionen dieser lat/lon-Paare halten möchten, können Sie Partitionen auf diesen Feldern in MySQL verwenden können, aus der Tatsache, dass sie ganze Zahlen sind zu profitieren:

Create Table: CREATE TABLE `Locations` (
    `lat` int(10) unsigned NOT NULL, 
    `lon` int(10) unsigned NOT NULL, 
    `location` text, 
    PRIMARY KEY (`lat`,`lon`) USING BTREE, 
    KEY `index_location` (`locationText`(30)) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 
/*!50100 PARTITION BY KEY() 
PARTITIONS 100 */ 
Verwandte Themen