Какой тип данных использовать при хранении данных о широте и долготе в базах данных SQL?[дубликат]

StackOverflow https://stackoverflow.com/questions/1196415

Вопрос

Какой тип данных был бы наиболее подходящим при хранении данных о широте или долготе в базе данных, совместимой с ANSI SQL?Следует float быть использованным, или decimal, или ...?

Я знаю, что Oracle, MySQL и SQL Server добавили некоторые специальные типы данных специально для обработки географических данных, но меня интересует, как вы будете хранить информацию в "простой ванильной" базе данных SQL.

Это было полезно?

Решение

Decimal(9,6)

Если вы не привыкли к параметрам точности и масштабирования, вот визуальная строка формата:

###.######

Другие советы

Мы используем float , но любой вариант числового значения с 6 знаками после запятой также должен работать.

Ну, вы спросили, как сохранить широту / долготу, и мой ответ таков:Не делайте этого, вы могли бы рассмотреть возможность использования WGS 84 ( в Европе ETRS 89 ) поскольку это стандарт для географических ссылок.

Но если оставить в стороне эту деталь, я использовал пользовательский тип за несколько дней до того, как SQL 2008 наконец включил поддержку geo.

В ванильном Oracle функция под названием LOCATOR (искаженная версия Spatial) требует, чтобы данные координат хранились с использованием типа данных NUMBER (без точности).Когда вы пытаетесь создать индексы на основе функций для поддержки пространственных запросов, в противном случае это приведет к сбою.

Вы можете легко сохранить десятичное число lat / lon в целочисленном поле без знака вместо того, чтобы разделять их на целую и десятичную части и сохранять их отдельно, как несколько предлагается здесь, используя следующий алгоритм преобразования:

как сохраненная функция mysql:

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)

и обратно

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

Это должно быть сохранено в беззнаковый int(10), это работает как в mysql, так и в sqlite, который не имеет типов.

по опыту я нахожу, что это работает действительно быстро, если все, что вам нужно, это сохранить координаты и извлечь их для выполнения некоторой математики.

в php эти 2 функции выглядят следующим образом

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

и снова назад:

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

Это также имеет некоторое дополнительное преимущество с точки зрения создания, например, уникальных ключей memcached с целыми числами.(бывший:для кэширования результата геокодирования).Надеюсь, это добавит ценности обсуждению.

Другим приложением может быть, когда у вас нет расширений GIS и вы просто хотите сохранить несколько миллионов таких пар широта / долгота, вы можете использовать разделы для этих полей в mysql, чтобы извлечь выгоду из того факта, что они являются целыми числами:

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

Я бы использовал десятичную дробь с надлежащей точностью для ваших данных.

Я думаю, это зависит от операций, которые вам нужно будет выполнять чаще всего.

Если вам нужно полное значение в виде десятичного числа, то используйте десятичное с соответствующей точностью и масштабом.Я полагаю, что Float выходит далеко за рамки ваших потребностей.

Если вы будете часто преобразовывать в / из дробной записи "degºmin'sec", я бы рассмотрел возможность сохранения каждого значения в виде целочисленного типа (smallint, tinyint, tinyint, smallint?).

Вам следует взглянуть на новые типы пространственных данных, которые были представлены в SQL Server 2008.Они специально разработаны для такого рода задач и значительно упрощают индексацию и запрос данных.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top