Lors du stockage de données de latitude ou de longitude dans une base de données compatible ANSI SQL, quel type de données serait le plus approprié? Faut-il utiliser float
ou decimal
ou ...?
Je suis conscient du fait qu'Oracle, MySql et SQL Server ont ajouté des types de données spéciaux spécifiquement pour la gestion des données géographiques, mais je voudrais savoir comment stocker ces informations dans une base de données SQL "plain Vanilla".
Decimal(9,6)
Si vous n’êtes pas habitué aux paramètres de précision et d’échelle, voici un visuel de format:
###.######
Nous utilisons float, mais toute variante numérique comportant 6 décimales devrait également fonctionner.
Eh bien, vous avez demandé comment enregistrer la latitude/longitude et ma réponse est la suivante: non, vous pouvez envisager d’utiliser le WGS 84 (en Europe ETRS 89 ) car c’est le norme pour les références géographiques.
Mais, mis à part ce détail, j’ai utilisé un type défini par l’utilisateur dans les jours qui ont précédé l’introduction du support géographique par SQL 2008.
Vous pouvez facilement stocker un nombre décimal lat/lon dans un champ entier non signé, au lieu de les diviser en une partie entière et décimale et de les stocker séparément, comme suggéré ici, en utilisant l'algorithme de conversion suivant:
en tant que fonction mysql stockée:
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)
et retour
CREATE DEFINER=`r`@`l` FUNCTION `PositionFloatToSmall`(s DECIMAL(10,7))
RETURNS int(10)
DETERMINISTIC
RETURN s * 600000
Cela doit être stocké dans un nsigned int (10), cela fonctionne aussi bien dans mysql que dans sqlite, qui est sans type.
par expérience, je trouve que cela fonctionne très vite, si tout ce que vous avez à faire est de stocker les coordonnées et de les récupérer pour faire des calculs.
en php ces 2 fonctions ressemblent
function LatitudeSmallToFloat($LatitudeSmall){
if(($LatitudeSmall>0)&&($LatitudeSmall>>31))
$LatitudeSmall=-(0x7FFFFFFF-($LatitudeSmall&0x7FFFFFFF))-1;
return (float)$LatitudeSmall/(float)600000;
}
et retour:
function LatitudeFloatToSmall($LatitudeFloat){
$Latitude=round((float)$LatitudeFloat*(float)600000);
if($Latitude<0) $Latitude+=0xFFFFFFFF;
return $Latitude;
}
Cela présente également un avantage supplémentaire en termes de création, par exemple, de clés uniques memcached avec des entiers. (ex: mettre en cache un résultat de géocodage). J'espère que cela ajoute de la valeur à la discussion.
Une autre application peut être lorsque vous n'avez pas d'extensions SIG et que vous voulez simplement conserver quelques millions de ces paires lat/lon. Vous pouvez utiliser des partitions sur ces champs dans mysql pour bénéficier du fait qu'elles sont des entiers:
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 */
Dans Vanilla Oracle, la fonctionnalité appelée LOCATOR (une version handicapée de Spatial) nécessite que les données de coordonnées soient stockées sous le type de données NUMBER (aucune précision). Lorsque vous essayez de créer des index basés sur les fonctions pour prendre en charge les requêtes spatiales, il en va autrement.
Jetez un coup d'œil aux nouveaux types de données Spatial introduits dans SQL Server 2008. Ils sont spécialement conçus pour ce type de tâche et rendent l'indexation et l'interrogation des données beaucoup plus simples et plus efficaces.
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
Je voudrais utiliser un nombre décimal avec la précision appropriée pour vos données.
Je pense que cela dépend des opérations que vous devrez effectuer le plus souvent.
Si vous avez besoin de la valeur complète sous forme de nombre décimal, utilisez décimal avec la précision et l'échelle appropriées. Flotter va bien au-delà de vos besoins, je crois.
Si vous convertissez souvent la notation en fraction vers/depuis degºmin'sec, il serait utile de stocker chaque valeur sous forme de type entier (smallint, tinyint, tinyint, smallint?).