ポリゴン列を使用してテーブルを作成する
空間インデックスを使用するには、InnoDBを使用できないことに注意してください。空間インデックスなしでジオメトリを使用することはできますが、パフォーマンスは通常どおり低下します。
CREATE TABLE IF NOT EXISTS `spatial` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`poly` geometry NOT NULL,
UNIQUE KEY `id` (`id`),
SPATIAL INDEX `poly` (`poly`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
3つの正方形と三角形を挿入します
INSERT INTO `spatial` (`poly`) VALUES (GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0))',0));
INSERT INTO `spatial` (`poly`) VALUES (GeomFromText('POLYGON((10 50,50 50,50 10,10 10,10 50))',0));
INSERT INTO `spatial` (`poly`) VALUES (GeomFromText('POLYGON((1 15,5 15,5 11,1 11,1 15))',0));
INSERT INTO `spatial` (`poly`) VALUES (GeomFromText('POLYGON((11 5,15 5,15 1,11 5))',0));
左下隅の小さな正方形と交差するものをすべて選択します (紫色の正方形#1)
SELECT id,AsText(poly) FROM `spatial`
WHERE
ST_Intersects(`poly`,
GEOMFROMTEXT('POLYGON((0 0,2 0,2 2,0 2,0 0))', 0 )
)
;
左下から右下隅、右上隅まで、三角形と交差するものをすべて選択してください) (正方形#1と#2および三角形#4)
SELECT id,AsText(poly) FROM `spatial`
WHERE
ST_Intersects(`poly`,
GEOMFROMTEXT('POLYGON((0 0,50 50,50 0,0 0))', 0 )
)
;
画像の外側にある正方形のすべてを選択します (なし)
SELECT id,AsText(poly) FROM `spatial`
WHERE
ST_Intersects(`poly`,
GEOMFROMTEXT('POLYGON((100 100,200 100,200 200,100 200,100 100))', 0 )
)
;
編集#1:
質問を読み直しましたが、空間的な関係が少し混乱していると思います。正方形(ポリゴン)の内側にぴったり収まるものをすべて見つけたい場合は、Contains/ST_Containsを使用する必要があります。 MySQLドキュメントの空間関数 を参照してください。 ST/MBR機能の次の違いに注意してください。
完全に正方形の内側にあるものをすべて選択します(下から#0) (正方形#1、#2、三角形#4)
SELECT id,AsText(poly) FROM `spatial`
WHERE
Contains(
GEOMFROMTEXT('POLYGON((0 0,20 0,20 20,0 20,0 0))', 0 ),
`poly`
)
;
完全に正方形の内側(下から#0)にあり、エッジを共有しないすべてのものを選択します (正方形#2、三角形#4)
SELECT id,AsText(poly) FROM `spatial`
WHERE
ST_Contains(
GEOMFROMTEXT('POLYGON((0 0,20 0,20 20,0 20,0 0))', 0 ),
`poly`
)
;
編集#2:
@StephanBからの非常に素晴らしい追加(SQLフィドル )
重複するオブジェクトを選択します
SELECT s1.id,AsText(s1.poly), s2.id, AsText(s2.poly)
FROM `spatial` s1, `spatial` s2
WHERE
ST_Intersects(s1.poly, s2.poly)
AND s1.id < s2.id
;
(AND s1.id < s2.id
を削除する必要があることに注意してください CONTAINS
を使用している場合 、as CONTAINS(a,b) <> CONTAINS(b,a)
一方、Intersects(a,b) = Intersects(b,a)
)
次の図(網羅的ではないリスト):
-
2は#6と交差します。
-
6は#2と交差します
-
0は#1、#2、#3、#4、#5と交差します
-
1は#0、#5と交差します
-
0には#1、#3、#4、および#5が含まれます(#1、#3、#4、および#5は#0内にあります)
-
1には#5が含まれています(#5は#1内にあります)
-
0 st_contains#3、#4、および#5
-
1 st_contains#5
編集#3:距離による検索/サークル内での作業
MySQLは、ジオメトリとして円を直接サポートしていませんが、空間関数Buffer(geometry,distance)
を使用できます。 それを回避する。 Buffer()
とは は、ジオメトリの周りに上記の距離のバッファを作成しています。ジオメトリポイントから始める場合、バッファは確かに円です。
次のコマンドを呼び出すだけで、バッファが実際に何をするかを確認できます:
SELECT ASTEXT(BUFFER(GEOMFROMTEXT('POINT(5 5)'),3))
(結果は非常に長いので、ここには投稿しません)実際には、バッファーを表すポリゴンが作成されます。この場合(および私のMariaDB)の結果は、円に近接する126ポイントのポリゴンです。このようなポリゴンを使用すると、他のポリゴンと同じように作業できます。したがって、パフォーマンスの低下はありません。
したがって、円に分類されるすべてのポリゴンを選択したい場合 すすぎ、前の例を繰り返すことができます(これは正方形#3だけを見つけます)
SELECT id,AsText(poly) FROM `spatial`
WHERE
ST_Contains(
Buffer(GEOMFROMTEXT('POINT(6 15)'), 10),
`poly`
)
;
円と交差するすべてのポリゴンを選択します
SELECT id,AsText(poly) FROM `spatial`
WHERE
ST_Intersects(
Buffer(GEOMFROMTEXT('POINT(6 15)'), 10),
`poly`
)
;
長方形とは異なる形状で作業する場合は、ST_*
を使用する必要があります 関数。 ST_
のない関数 境界矩形を使用します。したがって、前の例では、三角形が円の中になくても、三角形#4を選択します。
Buffer()
として 非常に大きなポリゴンを作成する場合、ST_Distance()
を使用するよりもパフォーマンスが低下することは間違いありません。 方法。残念ながら、それを定量化することはできません。ベンチマークを行う必要があります。
距離でオブジェクトを検索する別の方法は、ST_Distance()
を使用することです。 働き。
テーブルからすべての要素を選択し、ポイントPOINT(6 15)からの距離を計算します
SELECT id, AsText(`poly`),
ST_Distance(poly, GeomFromText('POINT(6 15)'))
FROM `spatial`
;
ST_Distance
を使用できます WHERE
条項も同様です。
POINT(0 0)からの距離が10以下のすべての要素を選択します (#1、#2、#3を選択)
SELECT id, AsText(`poly`),
ST_Distance(poly, GeomFromText('POINT(6 15)'))
FROM `spatial`
WHERE ST_Distance(poly, GeomFromText('POINT(6 15)')) <= 10
;
距離は最も近い点から最も近い点まで計算されますが。 ST_Intersect
に似せて 。したがって、上記の例では、完全に円の内側に収まらない場合でも、#2を選択します。
はい、GeomFromText(text,srid)
の2番目の引数(0) 、何の役割も果たしません。無視しても問題ありません。私はいくつかのサンプルからそれを拾い上げました、そしてそれは私の答えにちょっと立ち往生しています。後の編集で省略しました。
ところで。 phpMyAdmin 空間拡張のサポートは完璧ではありませんが、データベースに何があるかを確認するのにかなり役立ちます。添付したこれらの画像を手伝ってくれました。