Welcher Datentyp ist am besten geeignet, wenn Breiten- oder Längengraddaten in einer ANSI SQL-kompatiblen Datenbank gespeichert werden? Soll float
verwendet werden oder decimal
oder ...?
Ich bin mir bewusst, dass Oracle, MySQL und SQL Server einige spezielle Datentypen speziell für den Umgang mit Geodaten hinzugefügt haben, aber ich bin daran interessiert, wie Sie die Informationen in einer einfachen Vanilla-SQL-Datenbank speichern würden.
Decimal(9,6)
Wenn Sie nicht an die Genauigkeit und Skalierung von Parametern gewöhnt sind, finden Sie hier eine visuelle Formatzeichenfolge:
###.######
Wir verwenden float, aber jeder numerische Flavor mit 6 Dezimalstellen sollte auch funktionieren.
Nun, Sie haben gefragt, wie Breitengrad/Längengrad gespeichert werden soll, und meine Antwort lautet: Nein, Sie könnten erwägen, das WGS 84 (in Europa ETRS 89 ) zu verwenden, da es das ist Standard für Geo-Referenzen.
Abgesehen von diesen Details habe ich in den Tagen vor der endgültigen Unterstützung von SQL 2008 einen benutzerdefinierten Typ verwendet.
Sie können ganz einfach eine Lat/Lon-Dezimalzahl in einem vorzeichenlosen Ganzzahlfeld speichern, anstatt sie in einen Ganzzahl- und einen Dezimalteil aufzuteilen und diese getrennt zu speichern.
als gespeicherte MySQL-Funktion:
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 zurück
CREATE DEFINER=`r`@`l` FUNCTION `PositionFloatToSmall`(s DECIMAL(10,7))
RETURNS int(10)
DETERMINISTIC
RETURN s * 600000
Das muss in einem nsigned int (10) gespeichert werden, das funktioniert sowohl in mysql als auch in sqlite, das typenlos ist.
erfahrungsgemäß funktioniert dies sehr schnell, wenn Sie nur Koordinaten speichern und die Koordinaten abrufen müssen, mit denen Sie rechnen können.
in php sehen diese 2 funktionen so aus
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;
}
Dies hat einen zusätzlichen Vorteil, wenn beispielsweise zwischengespeicherte eindeutige Schlüssel mit ganzen Zahlen erstellt werden. (Beispiel: um ein Geocode-Ergebnis zwischenzuspeichern). Hoffe, dies fügt der Diskussion einen Mehrwert hinzu.
Eine andere Anwendung könnte sein, wenn Sie ohne GIS-Erweiterungen sind und einfach ein paar Millionen dieser Lat/Lon-Paare behalten möchten. Sie können Partitionen in diesen Feldern in mysql verwenden, um von der Tatsache zu profitieren, dass es sich um Ganzzahlen handelt:
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 */
In Vanilla Oracle erfordert die Funktion LOCATOR (eine verkrüppelte Version von Spatial), dass die Koordinatendaten mit dem Datentyp NUMBER (keine Genauigkeit) gespeichert werden. Wenn Sie versuchen, funktionsbasierte Indizes zu erstellen, um räumliche Abfragen zu unterstützen, wird dies andernfalls geknebelt.
Werfen Sie einen Blick auf die neuen Spatial-Datentypen, die in SQL Server 2008 eingeführt wurden. Sie wurden speziell für diese Art von Aufgaben entwickelt und machen das Indizieren und Abfragen der Daten wesentlich einfacher und effizienter.
http://msdn.Microsoft.com/en-us/library/bb933876 (v = sql.105) .aspx
http://blogs.technet.com/andrew/archive/2007/11/26/sql-server-2008-spatial-data-types.aspx
Ich würde eine Dezimalstelle mit der richtigen Genauigkeit für Ihre Daten verwenden.
Ich denke, es hängt von den Operationen ab, die Sie am häufigsten ausführen müssen.
Wenn Sie den vollständigen Wert als Dezimalzahl benötigen, verwenden Sie die Dezimalzahl mit der entsprechenden Genauigkeit und Skalierung. Float geht weit über Ihre Bedürfnisse hinaus, glaube ich.
Wenn Sie häufig in/von der Bruchnotation "degºmin'sec" konvertieren, würde ich in Betracht ziehen, jeden Wert als Ganzzahltyp zu speichern (smallint, tinyint, tinyint, smallint?).