MySQLの特定の半径内のクエリポイント
-
18-09-2019 - |
質問
次のMySQLテーブルを作成して、各ポイントの名前とともに緯度/経度座標を保存しました。
CREATE TABLE `points` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(128) NOT NULL,
`location` point NOT NULL,
PRIMARY KEY (`id`),
SPATIAL KEY `location` (`location`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;
私は質問しようとしています:
- an内のすべてのポイント n 特定のポイントのマイル半径。
- 与えられたポイントから返された各ポイントの距離
私が見つけたすべての例は、半径ではなく最小境界長方形(MBR)を使用することを参照しています。テーブルには約100万ポイントが含まれているため、このニーズはできるだけ効率的である必要があります。
解決 2
両方の回答をありがとう。
最終的には解決策を見つけました http://www.movable-type.co.uk/scripts/latlong-db.html.
他のヒント
MySQL 5.7+の場合
次の簡単なテーブルがあることを考えると、
create table example (
id bigint not null auto_increment primary key,
lnglat point not null
);
create spatial index example_lnglat
on example (lnglat);
次の簡単なデータを使用して、
insert into example (lnglat)
values
(point(-2.990435, 53.409246)),
(point(-2.990037, 53.409471)),
(point(-2.989736, 53.409676)),
(point(-2.989554, 53.409797)),
(point(-2.989350, 53.409906)),
(point(-2.989178, 53.410085)),
(point(-2.988739, 53.410309)),
(point(-2.985874, 53.412656)),
(point(-2.758019, 53.635928));
次のST機能の組み合わせで、別のポイントの特定の範囲内でポイントを取得します(注:ポリゴン内で検索する必要があります)。
set @px = -2.990497;
set @py = 53.410943;
set @range = 150; -- meters
set @rangeKm = @range / 1000;
set @search_area = st_makeEnvelope (
point((@px + @rangeKm / 111), (@py + @rangeKm / 111)),
point((@px - @rangeKm / 111), (@py - @rangeKm / 111))
);
select id,
st_x(lnglat) lng,
st_y(lnglat) lat,
st_distance_sphere(point(@px, @py), lnglat) as distance
from example
where st_contains(@search_area, lnglat);
結果としてこのようなものが表示されるはずです。
3 -2.989736 53.409676 149.64084252776277
4 -2.989554 53.409797 141.93232714661812
5 -2.98935 53.409906 138.11516275402533
6 -2.989178 53.410085 129.40289289527473
距離を参照するために、制約を削除すると、テストポイントの結果は次のようになります。
1 -2.990435 53.409246 188.7421181457556
2 -2.990037 53.409471 166.49406509160158
3 -2.989736 53.409676 149.64084252776277
4 -2.989554 53.409797 141.93232714661812
5 -2.98935 53.409906 138.11516275402533
6 -2.989178 53.410085 129.40289289527473
7 -2.988739 53.410309 136.1875540498202
8 -2.985874 53.412656 360.78532732013963
9 -2.758019 53.635928 29360.27797292756
注1: :ポイントを(x、y)と考える場合、それが正しい順序であり、ほとんどの関数(ポイントなど)もパラメーターを受け入れる場合、フィールドはlnglatと呼ばれます。
注2: :サークルを使用する場合、実際に空間インデックスを利用することはできません。また、ポイントフィールドはnullを受け入れるように設定できますが、空間インデックスがnullableであればインデックスはできないことに注意してください(インデックス内のすべてのフィールドは非ヌルである必要があります)。
注3: :st_bufferは(ドキュメントによって)このユースケースにとって悪いと見なされます
注4: :上記の関数(特にST_DISTANCE_SPHERE)は高速として文書化されていますが、必ずしも非常に正確ではありません。あなたのデータがそれに非常に敏感な場合、検索に少し小刻みの余地を追加し、結果セットに微調整を行います
RADIUSは効率的にインデックス可能ではありません。境界長方形を使用して、おそらく探しているポイントをすばやく取得し、半径の外側のポイントをフィルタリングする必要があります。
私は半径で円の内側で1ポイントそれをしました
SELECT
*
FROM
`locator`
WHERE
SQRT(POW(X(`center`) - 49.843317 , 2) + POW(Y(`center`) - 24.026642, 2)) * 100 < `radius`
詳細ともう1つのサンプルクエリはこちら http://dexxtr.com/post/83498801191/how-to-determine-point-inside-circle-using-mysql, 、 お役に立てれば