2009-07-28 13 views
227

Podczas przechowywania danych o szerokości i długości geograficznej w bazie danych zgodnej z ANSI SQL, jaki typ danych byłby najbardziej odpowiedni? Należy użyć float lub decimal lub ...?Jaki typ danych ma być używany podczas przechowywania danych o szerokości i długości geograficznej w bazach danych SQL?

Jestem świadomy, że Oracle, MySql i SQL Server dodały specjalne typy danych do obsługi danych geograficznych, ale jestem zainteresowany tym, jak zapisać informacje w bazie danych "zwykłej wanilii".

+18

W jaki sposób jest to duplikat pytania? On wyraźnie pyta o zwykłą wanilię bazy danych SQL, gdy inne pytanie (i tam też odpowiedzi) dyskutują o MySQL. – Atul

+4

Atul ma rację, nie jest to to samo pytanie, ponieważ drugi określa, że ​​obliczenia będą dokonywane na lat/lng. Właśnie zdałem sobie sprawę, że moja odpowiedź z drugiej najlepiej pasuje tutaj, więc proszę spojrzeć: http://stackoverflow.com/a/25120203/1226018 – Simon

+0

Mam zamiar zadzwonić, lata później. Atul i Simon mają rację. To są funkcjonalnie różne pytania. Oznaczenie tego jako duplikatu może być równoznaczne z stwierdzeniem, że pytanie, jak utrwalić rekord w bazie danych przy użyciu C# i Pythona, jest duplikatami. –

Odpowiedz

331

Decimal(9,6)

Jeśli nie jesteś przyzwyczajony do parametrów precyzji i skali, oto ciąg formatu wizualny:

###.######

+19

+1: Unikaj dziwności błędów zaokrąglania za pomocą ustalonej liczby miejsc dziesiętnych. –

+9

Dla ich celów Wikipedia sugeruje: "Unikaj nadmiernej precyzji (0,0001 ° to <11 m, 1" to <31 m). " http://pl.wikipedia.org/wiki/Wikipedia:Obtaining_geographic_coordinates Aby uczynić moje pola bardziej precyzyjnymi, postanowiłem również użyć sześciu cyfr od prawej do znaku dziesiętnego, a trzy po lewej. Cieszę się, że ta odpowiedź potwierdza, że ​​była to dobra decyzja. –

+1

Sprawdź ostatnią odpowiedź, ale jedną w tym [artykule] (http://groups.google.com/group/google-maps-api/browse_thread/thread/b928b5fbc5351821). Użytkownik William wyjaśnia bardzo dobrze, co dzieje się z precyzją, podczas gdy ty dostaniesz się daleko od równika. – Throoze

5

Używamy float, ale każdy smak numeryczna z 6 miejsc po przecinku powinna również działa.

+27

Obliczenia mogą wprowadzić dodatkowe cyfry, które byłyby tylko szumem. Również transformacja dziesiętna-binarna sprawi, że ostatnie miejsce dziesiętne będzie podejrzane i prawdopodobnie błędne. Dobra do niektórych celów. Kiepska nawigacja. –

+4

S> Lott, chciałbym nagłośnić twój komentarz Milion razy, gdybym mógł, nigdy nie używać pływaka przez długi i długi. – HLGEM

+1

Nie sądzę, aby sugerowanie pływaka zasługiwało na obniżenie - zmusiło mnie to do odgadnięcia i szukania gdzie indziej odpowiedzi: http://stackoverflow.com/questions/551894/whats-the-best-way-to-store -koordynacje-długość-szerokość-od-google-mapy – Keith

1

Używałbym dziesiętnych z właściwą precyzją dla twoich danych.

1

Myślę, że to zależy od operacji, które będziesz musiał wykonywać najczęściej.

Jeśli potrzebujesz pełnej wartości jako liczby dziesiętnej, użyj dziesiętnej z odpowiednią precyzją i skalą. Myślę, że Float jest daleko ponad twoje potrzeby.

Jeśli będziesz konwersji do/z degºmin'sec "notacji frakcji często Pomyślę przechowywania każdą wartość jako typ Integer (smallint, tinyint, tinyint, smallint?).

1

dobrze, zapytał, jak przechowywać Latitude/długość i moja odpowiedź brzmi: nie, można rozważyć użycie WGS 84 (w Europie ETRS 89), ponieważ jest to standard odniesienia Geo

Ale to szczegół bok użyłem typ zdefiniowany przez użytkownika. w ostatnich dniach SQL 2008 w końcu zawiera obsługę geolokacji:

2

W vanilla Oracle, funkcja ca LOCATOR (ułomna wersja Spatial) wymaga, aby dane współrzędnych były przechowywane przy użyciu typu danych NUMBER (brak precyzji). Kiedy próbujesz utworzyć indeksy oparte na funkcjach, aby obsługiwać zapytania przestrzenne, w przeciwnym wypadku będzie gag.

2

można łatwo przechowywać lat/lon liczbę dziesiętną w unsigned polu całkowitą, zamiast dzieląc je na całkowitą i część dziesiętną i przechowywania tych oddzielnie jako nieco sugeruje tutaj używając następujący algorytm konwersji:

w zapamiętanej funkcji 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) 

iz powrotem

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

To musi być przechowywany w unsigned int (10), to działa w mysql jak i SQLite, który jest typeless.

Z doświadczenia wiem, że działa to bardzo szybko, jeśli wszystko, co musisz, to współrzędne sklepu i pobrać te, z których można zrobić matematykę.

php 2 Funkcje te wyglądają

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

i z powrotem:

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

ten część dodatkową zaletę, a także w okresie tworzenia na przykład Memcached unikalne klucze całkowitymi. (np. buforować wynik geokodowania). Mam nadzieję, że to doda wartości do dyskusji.

Innym zastosowaniem może być, gdy jesteś bez rozszerzeń GIS i po prostu chcesz zachować kilka milionów tych lat/lon parami, można użyć partycji na tych pól w mysql skorzystać z faktu, że są liczbami całkowitymi:

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