什么MySQL数据类型应该用于纬度/经度8位小数?

时间:2012-09-19 23:21:32

标签: mysql types floating-point

我正在使用地图数据,Latitude/Longitude扩展到8位小数。例如:

Latitude 40.71727401
Longitude -74.00898606

我在Google document中看到了 使用:

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

然而,他们的小数位只有6 我应该使用FLOAT(10, 8)还是有其他方法来考虑存储这些数据,这样才能准确。它将与地图计算一起使用。谢谢!

9 个答案:

答案 0 :(得分:504)

DECIMAL是用于精确算术的MySQL数据类型。与FLOAT不同,它的精度对于任何数量的大小都是固定的,因此通过使用它而不是FLOAT,可以避免在进行某些计算时出现精度错误。如果您只是在不计算的情况下存储和检索数字,那么在实践中FLOAT是安全的,尽管使用DECIMAL没有任何害处。通过计算FLOAT仍然大部分没问题,但绝对确定8d.p.精度你应该使用DECIMAL。

纬度范围从-90到+90(度),所以DECIMAL(10,8)就可以了,但经度范围从-180到+180(度),所以你需要DECIMAL(11,8)。第一个数字是存储的总位数,第二个数字是小数点后面的数字。

简而言之:lat DECIMAL(10, 8) NOT NULL, lng DECIMAL(11, 8) NOT NULL

This解释了MySQL如何使用浮点数据类型。

答案 1 :(得分:13)

此外,您会看到float值已四舍五入。

// e.g: given values 41.0473112,29.0077011

float(11,7) | decimal(11,7)
---------------------------
41.0473099  | 41.0473112
29.0077019  | 29.0077011

答案 2 :(得分:6)

您可以将数据类型设置为有符号整数。将坐标存储到SQL时,可以设置为lat * 10000000和long * 10000000。当您选择距离/半径时,您将存储坐标划分为10000000.我用300K行测试它,查询响应时间很好。 (2 x 2.67GHz CPU,2 GB RAM,MySQL 5.5.49)

答案 3 :(得分:2)

laravel中的

使用小数列类型进行迁移

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

有关更多信息,see可用的列类型

答案 4 :(得分:1)

在我的情况下,最好的方法是将坐标保存为DOUBLE。

> python prog1.py | python prog2.py

它将保存整个值而不进行任何舍入。

如果您需要对值进行舍入,我的建议是此处理是在数据的原点完成的,例如在UI中。

答案 5 :(得分:1)

自从问这个问题以来,MySQL现在已经支持空间数据类型。因此,当前接受的答案是正确的,但是如果您要查找其他功能(例如查找给定面内的所有点),则可以使用POINT数据类型。

Checkout the Mysql Docs on Geospatial data typesspatial analysis functions

答案 6 :(得分:1)

CREATE TABLE your_table_name (
   lattitude  REAL,
   longitude  REAL
)

还可以考虑在您的经纬度声明中添加进一步的验证:

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))
)

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

答案 7 :(得分:0)

在rails上使用migrate ruby​​

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

答案 8 :(得分:0)

我认为在MySQL中存储Lat / Lng的最好方法是使用带有SPATIAL索引的POINT列(2D数据类型)。

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