306

我正在处理地图数据,并且Latitude/Longitude扩展到小数点后 8 位。例如:

Latitude 40.71727401
Longitude -74.00898606

我在Google 文档中看到 它使用:

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

但是,它们的小数位只能到 6。
我应该使用FLOAT(10, 8)还是有另一种方法可以考虑存储这些数据,以便精确。它将与地图计算一起使用。谢谢!

4

11 回答 11

672

MySQL 支持Spatial 数据类型Point是可以使用的单值类型。例子:

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));
于 2012-09-19T23:39:41.177 回答
51

在 laravel 中使用十进制列类型进行迁移

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

有关更多信息, 请参阅可用的列类型

于 2019-04-21T06:07:43.603 回答
22

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

// 例如:给定值 41.0473112,29.0077011

浮动(11,7) | 十进制(11,7)
--------------------------
41.0473099 | 41.0473112
29.0077019 | 29.0077011

于 2015-05-24T19:01:06.650 回答
10

不要使用浮点数...它会使您的坐标四舍五入,从而导致一些奇怪的事件。

使用小数

于 2018-02-27T01:13:18.827 回答
8

我相信在 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));
于 2019-07-15T13:30:00.913 回答
7

自从提出这个问题以来,MySQL 现在已经支持空间数据类型。因此,当前接受的答案没有错,但如果您正在寻找附加功能,例如查找给定多边形内的所有点,请使用 POINT 数据类型。

查看有关地理空间数据类型和空间分析功能的 Mysql 文档

于 2019-03-16T13:37:44.030 回答
6

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

于 2016-05-09T23:59:40.977 回答
4

小数点后 6 位的精度约为 16 厘米,这意味着如果两个物体之间的距离小于 16 厘米,则它们具有相同的 lat 和 lng。

此外,在 mariadb/mysql 中,如果我们有大量数据用于索引,则使用 float/double 并不理想,而 Point 数据类型是数据大小的开销。最好使用十进制或将 lat long 转换为 INT。

使用带 6 个小数位的小数是一个不错的选择,因为我们可以忽略转换,并且我们只有 16 厘米的误差,经度在 -180 到 180 之间,因此需要比纬度多 1 位,在 -90 到 90 度之间:

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

我们可以扩展到小数点后 8 位:

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

MySQL 参考

Mariadb 参考资料

于 2021-10-20T13:22:32.183 回答
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

于 2021-03-05T10:40:42.883 回答
-3

在 Rails 上使用迁移 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
于 2017-06-02T18:07:45.680 回答
-5

你应该简单地使用varchar (20)

于 2021-10-27T08:20:20.797 回答