What MySQL data type should be used for Latitude/Longitude with 8 decimal places?

MysqlTypesFloating Point

Mysql Problem Overview


I'm working with map data, and the Latitude/Longitude extends to 8 decimal places. For example:

Latitude 40.71727401
Longitude -74.00898606

I saw in the [Google document][1] which uses:

lat FLOAT( 10, 6 ) NOT NULL,  
lng FLOAT( 10, 6 ) NOT NULL

however, their decimal places only go to 6.
Should I use FLOAT(10, 8) or is there another method to consider for storing this data so it's precise. It will be used with map calculations. Thanks!

[1]: https://developers.google.com/maps/articles/phpsqlsearch_v3#createtable "Google Document"

Mysql Solutions


Solution 1 - Mysql

MySQL supports Spatial data types and Point is a single-value type which can be used. Example:

CREATE TABLE `buildings` (
  `coordinate` POINT NOT NULL,
  /* Even from v5.7.5 you can define an index for it */
  SPATIAL INDEX `SPATIAL` (`coordinate`)
) ENGINE=InnoDB;

/* then for insertion you can */
INSERT INTO `buildings` 
(`coordinate`) 
VALUES
(POINT(40.71727401 -74.00898606));

Solution 2 - Mysql

in laravel used decimal column type for migration

$table->decimal('latitude', 10, 8);
$table->decimal('longitude', 11, 8);

for more information see available column type

Solution 3 - Mysql

Additionally, you will see that float values are rounded.

// e.g: given values 41.0473112,29.0077011

float(11,7) | decimal(11,7)

41.0473099 | 41.0473112 29.0077019 | 29.0077011

Solution 4 - Mysql

Do not use float... It will round your coordinates, resulting in some strange occurrences.

Use decimal

Solution 5 - Mysql

I believe the best way to store Lat/Lng in MySQL is to have a POINT column (2D datatype) with a SPATIAL index.

CREATE TABLE `cities` (
  `zip` varchar(8) NOT NULL,
  `country` varchar (2) GENERATED ALWAYS AS (SUBSTRING(`zip`, 1, 2)) STORED,
  `city` varchar(30) NOT NULL,
  `centre` point NOT NULL,
  PRIMARY KEY (`zip`),
  KEY `country` (`country`),
  KEY `city` (`city`),
  SPATIAL KEY `centre` (`centre`)
) ENGINE=InnoDB;


INSERT INTO `cities` (`zip`, `city`, `centre`) VALUES
('CZ-10000', 'Prague', POINT(50.0755381, 14.4378005));

Solution 6 - Mysql

MySQL now has support for spatial data types since this question was asked. So the the current accepted answer is not wrong, but if you're looking for additional functionality like finding all points within a given polygon then use POINT data type.

Checkout the Mysql Docs on Geospatial data types and the spatial analysis functions

Solution 7 - Mysql

You can set your data-type as signed integer. When you storage coordinates to SQL you can set as lat10000000 and long10000000. And when you selecting with distance/radius you will divide storage coordinates to 10000000. I was test it with 300K rows, query response time is good. ( 2 x 2.67GHz CPU, 2 GB RAM, MySQL 5.5.49 )

Solution 8 - Mysql

Accuracy of 6 decimal places is about 16cm, which means 2 object have the same lat and lng if they are less than 16cm far from each other.

Also, in mariadb/mysql, using float/double is not ideal if we have huge data for indexing, and Point datatype is overhead for data size. It'd better to use decimal or convert lat long to INT.

It's good option to use decimal with 6 decimal places as we can ignore convert, and we have only 16cm inaccuracy, longitude is between -180 to 180, thus require 1 digit more than latitude, which is between -90 to 90 degree:

Lat DECIMAL(8,6)
Lng DECIMAL(9,6) 

We can extend to 8 decimal places:

Lat DECIMAL(10,8)
Lng DECIMAL(11,8) 

MySQL reference

Mariadb reference

Solution 9 - Mysql

CREATE TABLE your_table_name (
   lattitude  REAL,
   longitude  REAL
)

also consider adding further verifications to your lat, long declaration:

CREATE TABLE your_table_name (
   lattitude  REAL CHECK(lattitude IS NULL OR (lattitude >= -90 AND lattitude <= 90)),
   longitude  REAL CHECK(longitude IS NULL OR (longitude >= -180 AND longitude <= 180))
)

explanation : https://dev.mysql.com/doc/refman/5.7/en/floating-point-types.html

Solution 10 - Mysql

Using migrate ruby on rails

class CreateNeighborhoods < ActiveRecord::Migration[5.0]
  def change
    create_table :neighborhoods do |t|
      t.string :name
      t.decimal :latitude, precision: 15, scale: 13
      t.decimal :longitude, precision: 15, scale: 13
      t.references :country, foreign_key: true
      t.references :state, foreign_key: true
      t.references :city, foreign_key: true

      t.timestamps
    end
  end
end

Solution 11 - Mysql

You should simply use varchar (20)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEdwardView Question on Stackoverflow
Solution 1 - MysqlgandaliterView Answer on Stackoverflow
Solution 2 - MysqlJignesh JoisarView Answer on Stackoverflow
Solution 3 - MysqlK-GunView Answer on Stackoverflow
Solution 4 - MysqlSam SabeyView Answer on Stackoverflow
Solution 5 - MysqlΔO 'delta zero'View Answer on Stackoverflow
Solution 6 - MysqlBill--View Answer on Stackoverflow
Solution 7 - MysqlOğuzhan KURNUÇView Answer on Stackoverflow
Solution 8 - MysqlVengleab SOView Answer on Stackoverflow
Solution 9 - Mysql1kevinsonView Answer on Stackoverflow
Solution 10 - MysqlgilcierwebView Answer on Stackoverflow
Solution 11 - MysqlPirogrammerView Answer on Stackoverflow