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:フィールドはlnglatと呼ばれます。これは、ポイントを(x、y)と考える場合の正しい順序であり、ほとんどの関数(ポイントなど)がパラメーターを受け入れる順序でもあるためです。
注 2 : 円を使用する場合、空間インデックスを実際に利用することはできません。また、ポイント フィールドは null を受け入れるように設定できますが、null 許容の場合は空間インデックスでインデックス付けできないことにも注意してください (インデックス内のすべてのフィールドは null 以外である必要があります)。
注 3 : st_buffer は (ドキュメントによると) このユース ケースには不適切であると見なされています。
注 4 : 上記の関数 (特に st_distance_sphere) は高速であると記載されていますが、必ずしも超正確であるとは限りません。データが非常に機密性の高い場合は、検索に少し余裕を持たせて、結果セットを微調整します