Jakiego typu danych użyć podczas przechowywania danych szerokości i długości geograficznej w bazach danych SQL? [duplikat]

To pytanie ma już odpowiedź tutaj:

Podczas przechowywania danych szerokości lub 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 ...?

Zdaję sobie sprawę, że Wyrocznia, MySql i SQL Server dodały specjalne typy danych specjalnie do obsługi danych geograficznych, ale interesuje mnie, w jaki sposób można przechowywać informacje w "zwykłej" bazie danych SQL.

Author: j0k, 2009-07-29

8 answers

Decimal(9,6)

Jeśli nie jesteś przyzwyczajony do precyzji i skalowania parametrów, oto wizualizacja ciągu formatu:

###.######

 359
Author: dotjoe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-16 12:54:12

Używamy float, ale każdy smak numeryczny z 6 miejscami po przecinku również powinien działać.

 6
Author: Keith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-28 20:07:28

Cóż, zapytałeś jak przechowywać szerokość/długość geograficzną i moja odpowiedź brzmi: nie, możesz rozważyć użycie WGS 84 ( w Europie ETRS 89), ponieważ jest to standard dla odniesień geograficznych.

Ale ten szczegół na bok użyłem typu zdefiniowanego przez Użytkownika w dniach przed SQL 2008 w końcu obejmują wsparcie geo.

 3
Author: Kasper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-28 21:12:37

W Oracle funkcja o nazwie LOCATOR (spatial version of Spatial) wymaga, aby dane współrzędnych były przechowywane przy użyciu datatype of NUMBER (bez precyzji). Gdy spróbujesz utworzyć indeksy oparte na funkcjach, aby obsługiwać zapytania przestrzenne, to będzie inaczej.

 2
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-25 19:24:39

Możesz łatwo zapisać liczbę dziesiętną lat/lon w polu unsigned integer, zamiast dzielić je na liczbę całkowitą i dziesiętną i przechowywać je osobno, jak nieco sugerowano tutaj, używając następującego algorytmu konwersji:

Jako przechowywana funkcja 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)

I z powrotem

CREATE DEFINER=`r`@`l` FUNCTION `PositionFloatToSmall`(s DECIMAL(10,7)) 
RETURNS int(10)
DETERMINISTIC
RETURN s * 600000
W przeciwieństwie do SQL-a, nie jest to możliwe, ponieważ nie jest to możliwe.

Dzięki doświadczeniu stwierdzam, że to działa naprawdę szybko, jeśli wszystko, co musisz zrobić, to zapisać współrzędne i pobrać je, aby zrobić trochę matematyki.

W php te 2 funkcje wyglądają jak

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;
}

Ma to pewną dodatkową zaletę w postaci tworzenia na przykład unikalnych kluczy memcached z liczbami całkowitymi. (np. do buforowania wyniku geocode). Mam nadzieję, że to zwiększy wartość dyskusji.

Inna aplikacja może być, gdy jesteś bez rozszerzeń GIS i po prostu chcesz zachować kilka milionów z nich pary lat/lon, możesz użyć partycji na tych polach w mysql, aby 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 */
 2
Author: Glenn Plas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-22 15:10:45

Użyłbym dziesiętnego z odpowiednią precyzją dla Twoich danych.

 1
Author: Sam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-28 20:08:02

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ą dokładnością i skalą. Myślę, że Float wykracza poza twoje potrzeby.

Jeśli będziesz często konwertować do / z notacji ułamkowej degºmin ' sec, rozważyłbym przechowywanie każdej wartości jako typu integer (smallint, tinyint, tinyint, smallint?).

 1
Author: jpj625,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-28 20:11:57

Powinieneś przyjrzeć się nowym typom danych przestrzennych, które zostały wprowadzone w SQL Server 2008. Są one specjalnie zaprojektowane tego rodzaju zadania i sprawiają, że indeksowanie i odpytywanie danych jest znacznie łatwiejsze i bardziej wydajne.

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

 1
Author: syed Ahsan Jaffri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-05 17:49:17