Home > Mobile >  MariaDB and MySQL POINT type: In which order are Latitude and Longitude returned?
MariaDB and MySQL POINT type: In which order are Latitude and Longitude returned?

Time:08-09

When using geospatial column types such as POINT with MySQL and MariaDB, there is a lot of confusion about the order in which one should specify latitude and longitude (1,2,3), and different applications use different conventions. However, when using some functions - such as ST_DISTANCE_SPHERE - the order of lat and long matters.

In what order to specify Latitude and Longitude when creating a POINT in MySQL and MariaDB?

I slighted adapted an example from the MariaDB docs and tested this on MariaDB 10.6.7 and MySQL 8.0.28. Both databases return numerically identical results:

set @zenica   = ST_GeomFromText('POINT(17.907743 44.203438)');
set @sarajevo = ST_GeomFromText('POINT(18.413076 43.856258)');


set @zenica2   = ST_GeomFromText('POINT(44.203438 17.907743)');
set @sarajevo2 = ST_GeomFromText('POINT(43.856258 18.413076)');
SELECT ST_Distance_Sphere(@zenica, @sarajevo), ST_Distance_Sphere(@zenica2, @sarajevo2);
-- Result: 55878.59337591705    67103.51207765185

So in both MySQL and MariaDB, we should put long-lat format when creating POINTS, i.e. longitude goes first

In what order do MySQL and MariaDB return GIS coordinates?

When SELECTing a point, MySQL and MariaDB return a binary format of the point. However, I get a different response depending on which database I am using

CodePudding user response:

MySQL and MariaDB use incompatible binary formats for representing POINTs

Unfortunately, MySQL uses lon-lat in its binary format for POINT while MariaDB has the reverse. Here is some example code in PHP:

$testCase = DB::select("SELECT ST_PointFromText('POINT(24.00 12.00)', 4326) AS samplePoint")[0];
$testUnpacked = unpack("lSRID/CByteOrder/lTypeInfo/dFirst/dSecond", $testCase->samplePoint);
var_dump($testUnpacked['First'])
# double(12) -- MySQL output
# double(24) -- MariaDB output

When encountering this problem in my application, I needed to forgo explicitly checking for the database vendor using version strings or similar, and used "feature detection" instead - seeing what response I get for the testCase and adjusting the unpack format accordingly.

CodePudding user response:

In MySQL the interpretation depends on SRID you use with the data, and follows the SRID-defined order, thus latitude-longitude for SRID 4326. Without SRID (same as SRID=0) it uses longitude-latitude order. It is easy to check by e.g. passing location at the pole, 90:100 - with lat:lon order it is North pole, with lon:lat order it is incorrect data since latitude should be between -90 and 90.

In MySQL you can also use regular ST_Distance to compute distance (in meters) between points in SRID=4326, as it properly implements this geographic SRID:

-- MySQL 8.0
select 
-- ST_Distance_Sphere without SRID => lon lat order.
st_distance_sphere(
  st_geomfromtext('point(1 90)'),
  st_geomfromtext('point(100 90)')) AS dist_sphere_0,
-- ST_Distance with SRID => lat lon order.  
st_distance(
  st_geomfromtext('point(90 1)', 4326),
  st_geomfromtext('point(90 100)', 4326)) AS dist,
-- ST_Distance_Sphere with SRID => lat lon order.  
st_distance(
  st_geomfromtext('point(90 1)', 4326),
  st_geomfromtext('point(90 100)', 4326)) AS dist_sphere_4326;

All these return 0 or value very close to 0, since all these points have latitude 90 and describe North Pole.

MariaDB does not implement geographic SRID AFAIK, thus it allows any x/y values, ST_Distance still returns incorrect (planar) distance even with SRID=4326, and the order for ST_Distance_Sphere always seem to be longitude-latitude.

  • Related