私は地図データを扱っています、そして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)
を使うべきですか、それとも正確なのでこのデータを保存するために考慮すべき別の方法がありますか。これはマップ計算で使用されます。ありがとうございます。
DECIMALは正確な算術演算のためのMySQLデータ型です。 FLOATとは異なり、精度は任意のサイズの数値に対して固定されているため、FLOATの代わりにそれを使用すると、計算を行うときに精度エラーを回避できます。計算せずに数値を格納して取り出すだけなら、実際にはFLOATが安全ですが、DECIMALを使用しても問題ありません。計算ではFLOATはまだ大体問題ありませんが、8d.pを絶対に確実にするためです。精度はDECIMALを使用してください。
緯度は-90〜+ 90(度)の範囲であるため、DECIMAL(10、8)で問題ありませんが、経度は-180〜+ 180(度)の範囲であるため、DECIMAL(11、8)が必要です。最初の数字は保存されている桁数の合計です。2番目の数字は小数点の後の数字です。
一言で言えば:lat DECIMAL(10, 8) NOT NULL, lng DECIMAL(11, 8) NOT NULL
This MySQLがどのように浮動小数点データ型を扱うかを説明します。
さらに、float
の値が丸められているのがわかります。
//例:与えられた値41.0473112、29.0077011 float(11,7)| decimal(11,7) --------------------------- 41.0473099 | 41.0473112 29.0077019 | 29.0077011
データ型を符号付き整数として設定できます。 SQLへの格納座標は、lat * 10000000とlong * 10000000として設定できます。また、距離/半径で選択すると、格納座標を10000000に分割します。300K行でテストしたところ、クエリの応答時間は良好です。 (2 x 2.67GHz CPU、2 GB RAM、MySQL 5.5.49)
Floatを使用しないでください。座標が丸められて、奇妙なことが起こります。
10進数を使用
laravelでマイグレーションに使用される10進数列タイプ
$table->decimal('latitude', 10, 8);
$table->decimal('longitude', 11, 8);
詳細については 参照 available column type
私の場合の最良の方法はDOUBLEとして座標を保存することでした。
lat DOUBLE NOT NULL,
lng DOUBLE NOT NULL
丸めずに値全体を保存します。
値を四捨五入する必要がある場合は、この処理はデータの原点、たとえばUIで行われることをお勧めします。
この質問がされて以来、MySQLは空間データ型をサポートしています。したがって、現在受け入れられている答えは間違っていませんが、特定の多角形内のすべての点を見つけるなどの追加機能を探している場合は、POINTデータ型を使用します。
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
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));