2009-07-28 2 views
227

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

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

+18

Как этот дублирующий вопрос? Он явно задает абажую обычную базу данных базы данных ванили, когда другой вопрос (и ответы там тоже) обсуждает MySQL конкретно. – Atul

+4

Атул прав, это не тот же вопрос, потому что другой указывает, что вычисления будут производиться на lat/lng. Я только понял, что мой ответ от другого лучше всего подходит здесь, поэтому, пожалуйста, посмотрите: http://stackoverflow.com/a/25120203/1226018 – Simon

+0

Я собираюсь перезвонить, спустя годы. Атул и Саймон правы. Это функционально разные вопросы. Пометка этого как дубликата может быть эквивалентом того, что запрос о том, как сохранить запись в базе данных с использованием C# и Python, является дубликатом. –

ответ

331

Decimal(9,6)

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

###.######

+19

+1: Избегайте ошибки округления при использовании фиксированного числа знаков после запятой. –

+9

В своих целях Wikipedia предлагает: «Избегать чрезмерной точности (0,0001 ° <11 м, 1 '<31 м)». http://en.wikipedia.org/wiki/Wikipedia:Obtaining_geographic_coordinates Чтобы сделать мои поля более точными, я также решил использовать шесть цифр справа от десятичной метки и три слева. Я рад, что этот ответ подтверждает, что это было хорошее решение. –

+1

Проверьте последний ответ, кроме одного в этой статье [http://groups.google.com/group/google-maps-api/browse_thread/thread/b928b5fbc5351821). Пользователь Уильям очень хорошо объясняет, что происходит с точностью, пока вы далеко от экватора. – Throoze

5

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

+27

Расчет может ввести дополнительные цифры, которые будут только шумом. Кроме того, десятичное двоичное преобразование сделает конечное десятичное место подозрительным и, возможно, неправильным. Прекрасно для некоторых целей. Отвратительно для навигации. –

+4

S> Lott, я бы поднял ваш комментарий миллион раз, если бы мог, никогда не использовал float для lat и long. – HLGEM

+1

Я не думаю, что предлагать плавать заслуживает снижения - вы заставили меня задуматься и искать в другом месте для ответа: http://stackoverflow.com/questions/551894/whats-the-best-way-to-store -координаты-долгота-широта-от-google-maps – Keith

1

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

1

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

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

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

1

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

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

2

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

1

Вы должны взглянуть на новые пространственные типы данных, которые были введены в 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

2

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

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

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