2009-07-28 76 views
227

Al almacenar datos de latitud o longitud en una base de datos ANSI SQL, ¿qué tipo de datos sería el más apropiado? ¿Se debe usar float, o decimal, o ...?¿Qué tipo de datos usar al almacenar datos de latitud y longitud en bases de datos SQL?

Soy consciente de que Oracle, MySql y SQL Server han agregado algunos tipos de datos especiales específicamente para el manejo de datos geográficos, pero me interesa saber cómo se almacenaría la información en una base de datos SQL "simple".

+18

¿Cómo es esta pregunta duplicada? Claramente está preguntando sobre la simple base de datos SQL vainilla cuando la otra pregunta (y las respuestas allí también) discuten MySQL específicamente. – Atul

+4

Atul tiene razón, no es la misma pregunta porque el otro especifica que los cálculos se realizarán en lat/lng. Me acabo de dar cuenta de que mi respuesta del otro es la más adecuada aquí, así que por favor échele un vistazo: http://stackoverflow.com/a/25120203/1226018 – Simon

+0

Voy a tocar el timbre, años más tarde. Atul y Simon tienen razón. Estas son preguntas funcionalmente diferentes. Marcar esto como duplicado podría ser equivalente a afirmar que preguntar cómo mantener un registro en una base de datos usando C# y Python son duplicados. –

Respuesta

331

Decimal(9,6)

Si no está acostumbrado a los parámetros de precisión y escala, aquí está una cadena de formato visual:

###.######

+19

+1: Evita la rareza del error de redondeo al usar una cantidad fija de decimales. –

+9

Para sus fines Wikipedia sugiere: "Evite la precisión excesiva (0,0001 ° es <11 m, 1 '' es <31 m)." http://en.wikipedia.org/wiki/Wikipedia:Obtaining_geographic_coordinates Para que mis campos sean más precisos, también he decidido utilizar seis dígitos a la derecha de la marca decimal, y tres a la izquierda. Me alegra que esta respuesta confirme que fue una buena decisión. –

+1

Compruebe la última respuesta, pero una en este [artículo] (http://groups.google.com/group/google-maps-api/browse_thread/thread/b928b5fbc5351821). El usuario William explica muy bien lo que sucede con precisión mientras te alejas del ecuador. – Throoze

5

Utilizamos flotador, pero cualquier sabor de numérico con 6 decimales debe Además trabajo.

+27

Un cálculo podría introducir dígitos adicionales que solo serían ruido. Además, la transformación de decimal a binario hará que el decimal final sea sospechoso y posiblemente incorrecto. Está bien para algunos propósitos. Pésimo para la navegación. –

+4

S> Lott, yo hubiera votado vivamente su comentario un Millón de veces si pudiera, nunca use el flotador por latitud y longitud. – HLGEM

+1

No creo que la sugerencia de float merezca una rebaja: me hiciste una segunda aproximación y busques una respuesta en otro sitio: http://stackoverflow.com/questions/551894/whats-the-best-way-to-store -co-ordenadas-longitud-latitud-de-google-maps – Keith

1

Usaría un decimal con la precisión adecuada para sus datos.

1

Creo que depende de las operaciones que necesitará realizar con más frecuencia.

Si necesita el valor completo como número decimal, utilice decimales con la precisión y la escala adecuadas. Float va más allá de tus necesidades, creo.

Si va a convertir a/de degºmin'sec "notación de fracción menudo, me gustaría considerar almacenar cada valor como un tipo entero (smallint, tinyint, tinyint, smallint?).

1

Bueno, preguntó cómo almacenar latitud/longitud y mi respuesta es: no, es posible considerar el uso de la WGS 84 (en Europa ETRS 89), ya que es el estándar para las referencias Geo

Pero ese detalle de lado he usado un tipo definido por el usuario. en los días previos a SQL 2008, finalmente, incluye compatibilidad con geo.

2

En vainilla Oracle, la característica ca El LOCATOR lleno (una versión paralizada de Spatial) requiere que los datos de coordenadas se almacenen usando el tipo de datos de NUMBER (sin precisión). Cuando intente crear Índices basados ​​en funciones para admitir consultas espaciales, lo hará de otra manera.

2

Se pueden almacenar una latitud/longitud número decimal en un campo entero sin signo, en lugar de dividirlos en una entera y parte decimal y el almacenamiento de los separado como algo que aquí se sugiere el uso de el siguiente algoritmo de conversión:

como una función mysql almacenado:

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) 

y la espalda

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

que necesita ser almacenado en un unsigned int (10), esto funciona en MySQL, así como en sqlite que es sin tipo.

a través de la experiencia, creo que esto funciona muy rápido, si todo lo que necesita es almacenar las coordenadas y recuperarlas para hacer algunas operaciones matemáticas.

en php esos 2 funciones parecen

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

y vuelta a empezar:

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

Esto tiene cierta ventaja añadida, así en términos de la creación, por ejemplo, claves únicas memcached con números enteros. (por ejemplo, para almacenar en caché un resultado de geocodificación). Espero que esto agregue valor a la discusión.

Otra aplicación podría ser cuando se está sin extensiones de SIG y simplemente quiere mantener unos pocos millones de esos pares latitud/longitud, puede utilizar particiones en aquellos campos en MySQL para beneficiarse del hecho de que son números enteros:

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 */ 
Cuestiones relacionadas