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

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

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


person dthrasher    schedule 28.07.2009    source источник
comment
Атул прав, это не тот же вопрос еще и потому, что в другом указано, что расчеты будут производиться по широте / долготе. Я только что понял, что мой ответ от другого лучше всего подходит здесь, поэтому, пожалуйста, посмотрите: stackoverflow.com/a/25120203/1226018   -  person Simon    schedule 01.10.2015


Ответы (8)


Для широты используйте: Decimal(8,6), а для долготы используйте: Decimal(9,6).

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

Широта и долгота ##.###### и ###.######

6 знаков после запятой должны обеспечить точность координат примерно 10 см.

person dotjoe    schedule 28.07.2009
comment
+1: Избегайте странных ошибок округления, используя фиксированное количество десятичных знаков. - person S.Lott; 29.07.2009
comment
Для их целей Википедия предлагает: Избегайте чрезмерной точности (0,0001 ° составляет ‹11 м, 1 ′ ′ составляет‹ 31 м). en.wikipedia.org/wiki/ Чтобы мои поля были более точными, я Также решил использовать шесть цифр справа от десятичного знака и три слева. Я рад, что этот ответ подтверждает, что это хорошее решение. - person Dragoljub Ćurčić; 17.02.2010
comment
Проверьте последний, кроме одного, ответ в этой статье. Пользователь Уильям очень хорошо объясняет, что происходит с точностью, когда вы удаляетесь от экватора. - person Throoze; 15.04.2012
comment
Кроме того, если вы не собираетесь оперировать числами, подумайте о том, чтобы сохранить их в виде строки. Использование varchar(20) было бы более точным и недорогим в хранении. - person Throoze; 15.04.2012
comment
Забавно, я просто проверял, что я использовал хорошее значение DECIMAL (9,6) в БД, но он взаимодействует через NodeJS (который в любом случае передается как значение с плавающей запятой для БД), поэтому хотел дважды проверить. - person Tracker1; 13.12.2012
comment
(8,6) для широты и (9,6) для долготы - person Neil McGuigan; 27.09.2013
comment
почему широта (8,6) и долгота (9,6) ...?, по какой-либо причине?, почему не обе (9,6)? - person makitocode; 10.04.2015
comment
@ Широта Макито изменяется от -90 до 90 градусов ... так что нужно всего 2 разряда слева от десятичной точки ... - person dotjoe; 10.04.2015
comment
@Throoze Можете ли вы объяснить причину предложения varchar(20)? Я не буду выполнять никаких операций, кроме отправки координат в Google Maps API, поэтому мне любопытно узнать о преимуществах использования VARCHAR(20) вместо DECIMAL(9,6). Спасибо! - person Shiva; 26.03.2017
comment
Типы данных @Shiva well geolocation полезны только в том случае, если вы собираетесь работать с ними с любым драйвером или приложением ГИС. Но если вы собираетесь только хранить их, строки более чем достаточно. В любом случае, если вам нужно проделать какие-то необычные операции с сохраненными значениями, взгляните на эта статья, в которой подробно рассказывается о точности и использовании этих значений в приложении javascript. Думаю, это действительно зависит от вас. Помните, что API карт Google использует объекты Json, поэтому для них все является строкой. - person Throoze; 05.04.2017
comment
Что касается предложений по сохранению как VARCHAR, разве он не использует больше места, чем десятичная дробь с точностью до 9? -176.824107 в DECIMAL (9,6) займет 5 байтов, а в качестве VARCHAR - 11 байтов (в UTF-8). - person DrewF; 01.02.2020
comment
Очень нишевый случай, но Австралийский статистический комитет обеспечивает точность до 8 знаков после запятой, поэтому я использую 11,8 декабря. - person Shaedo; 05.09.2020

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

person Keith    schedule 28.07.2009
comment
При вычислении могут появиться дополнительные цифры, которые будут лишь шумом. Кроме того, преобразование десятичного числа в двоичное сделает последний десятичный разряд подозрительным и, возможно, неправильным. Для некоторых целей штраф. Паршивая для навигации. - person S.Lott; 29.07.2009
comment
Я не думаю, что предложение float заслуживает снижения - вы заставили меня задуматься и поискать ответ в другом месте: stackoverflow.com/questions/551894/ - person Keith; 29.07.2009
comment
Вопрос в хранении. 32-битное число с плавающей запятой - самый эффективный способ хранения. Если вам нужно выполнить много вычислений и вы можете показать, что ошибки округления имеют значение, то сначала приведите к 64-битному типу с плавающей запятой. - person nilskp; 02.07.2013

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

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

person Kasper    schedule 28.07.2009
comment
Мне любопытно, вы можете вспомнить, что вы имели в виду, когда предлагали не сохранять широту и долготу? Что вы думали сэкономить вместо этого? - person Matt Kieran; 15.04.2018
comment
Я не уверен, что здесь говорит Каспер. Широта / долгота - это формат положения (эквивалент UTM, MGRS, NZTM и т. Д.), Тогда как WGS84 - это датум - система отсчета, к которой применяются координаты положения. Вам необходимо знать обе координаты и данные, которые вы используете, хотя для онлайн-использования это почти всегда WGS84. - person Mike; 12.02.2020

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

http://msdn.microsoft.com/en-us/library/bb933876(v=sql.105).aspx

person syed Ahsan Jaffri    schedule 05.09.2012

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

person Sam    schedule 28.07.2009

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

person Community    schedule 25.08.2009

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

как сохраненная функция 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

Это необходимо сохранить в unsigned 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 с целыми числами. (например, для кеширования результата геокодирования). Надеюсь, это повысит ценность обсуждения.

Другое приложение может быть, если у вас нет расширений ГИС и вы просто хотите сохранить несколько миллионов этих пар lat / lon, вы можете использовать разделы в этих полях в 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 */
person Glenn Plas    schedule 18.09.2012

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

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

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

person jpj625    schedule 28.07.2009